Netty入门P1

传统Http服务器原理

传统Http服务创建连接的步骤:

  1. 创建一个ServerSocket,监听并绑定一个端口;
  2. 来自客户端对这个端口的请求;
  3. 服务器Accept,获得一个来自客户端的Socket连接对象;
  4. 启动新的处理线程;
    1. 读取Socket,获取字节流;
    2. 解码协议,获取Http请求对象;
    3. 处理Http请求,获得一个结果,封装为一个HttpResponse对象;
    4. 编码处理,将结果序列化为字节流写到Socket,将字节流发送给客户端;
  5. 循环执行第三步;

Http服务器之所以叫做Http服务器是因为编码解码协议使用的Http协议。

使用Netty就可以自定义编码解码协议。

什么是Socket

网络上的两个程序通过一个双向的通讯连接在一起实现数据的交换,这个连接的一端就是一个socket。
Netty入门P1

NIO

相对NIO,BIO是指:

  1. 客户端监听(Listen)时,Accept是阻塞的,只有新连接来了,Accept才会返回,主线程才能继续;
  2. 读写socket时,Read是阻塞的,只有请求消息来了,Read才能返回,子线程才能继续处理;
  3. 读写socket时,Write是阻塞的,只有客户端在接收完数据后,Write才可以返回,子线程才可继续处理下一个请求;

BIO可以看出自始至终所有线程都是阻塞的,在线程阻塞时,线程是白白占用系统资源,造成了系统资源利用率不高的问题。

NIO的非阻塞是怎么做到的?

使用事件机制。

一条线程处理从Accept、读写操作到请求处理所有事情,如果处理完毕没有任务可执行,则该线程则会被挂起。

粘包\拆包现象发生的原因

在应用层按照ByteBuf为单位发送数据,Server按照ByteBuf读取数据,但是系统底层仍然是按照字节流发送数据。

因此,在数据到了服务端后,也是按照字节流读取的,再到Netty应用层,从新拼装成ByteBuf,而在此出的ByteBuf可能是与发送端按顺序发送的ByteBuf可能是不对等的。

Netty的零拷贝

传统意义的拷贝:

在发送数据时:

  1. FIle.read(bytes);
  2. Socket.send(bytes);

此种方式需要四次数据拷贝和四次上下文切换:

  1. 数据从磁盘读取到内核的read buffer;
  2. 数据从内核缓冲区拷贝到用户缓冲区;
  3. 数据从用户缓冲区拷贝到内核的socket buffer;
  4. 数据从内核的socket buffer拷贝到网卡接口的缓冲区;

零拷贝,发送数据:

  1. 调用transferTo,数据从文件由DMA引擎拷贝到内核read buffer;
  2. 之后,DMA从内核read buffer将数据拷贝到网卡接口buffer上;

零拷贝的两次操作均不需要CPU参与。

Netty中的零拷贝体现在:

  1. bytebuffer;
  2. Composite Buffers;
  3. FileChannel.transferTo的使用;

参考自掘金大佬