Netty入门P1
传统Http服务器原理
传统Http服务创建连接的步骤:
- 创建一个ServerSocket,监听并绑定一个端口;
- 来自客户端对这个端口的请求;
- 服务器Accept,获得一个来自客户端的Socket连接对象;
- 启动新的处理线程;
- 读取Socket,获取字节流;
- 解码协议,获取Http请求对象;
- 处理Http请求,获得一个结果,封装为一个HttpResponse对象;
- 编码处理,将结果序列化为字节流写到Socket,将字节流发送给客户端;
- 循环执行第三步;
Http服务器之所以叫做Http服务器是因为编码解码协议使用的Http协议。
使用Netty就可以自定义编码解码协议。
什么是Socket
网络上的两个程序通过一个双向的通讯连接在一起实现数据的交换,这个连接的一端就是一个socket。
NIO
相对NIO,BIO是指:
- 客户端监听(Listen)时,Accept是阻塞的,只有新连接来了,Accept才会返回,主线程才能继续;
- 读写socket时,Read是阻塞的,只有请求消息来了,Read才能返回,子线程才能继续处理;
- 读写socket时,Write是阻塞的,只有客户端在接收完数据后,Write才可以返回,子线程才可继续处理下一个请求;
BIO可以看出自始至终所有线程都是阻塞的,在线程阻塞时,线程是白白占用系统资源,造成了系统资源利用率不高的问题。
NIO的非阻塞是怎么做到的?
使用事件机制。
一条线程处理从Accept、读写操作到请求处理所有事情,如果处理完毕没有任务可执行,则该线程则会被挂起。
粘包\拆包现象发生的原因
在应用层按照ByteBuf为单位发送数据,Server按照ByteBuf读取数据,但是系统底层仍然是按照字节流发送数据。
因此,在数据到了服务端后,也是按照字节流读取的,再到Netty应用层,从新拼装成ByteBuf,而在此出的ByteBuf可能是与发送端按顺序发送的ByteBuf可能是不对等的。
Netty的零拷贝
传统意义的拷贝:
在发送数据时:
- FIle.read(bytes);
- Socket.send(bytes);
此种方式需要四次数据拷贝和四次上下文切换:
- 数据从磁盘读取到内核的read buffer;
- 数据从内核缓冲区拷贝到用户缓冲区;
- 数据从用户缓冲区拷贝到内核的socket buffer;
- 数据从内核的socket buffer拷贝到网卡接口的缓冲区;
零拷贝,发送数据:
- 调用transferTo,数据从文件由DMA引擎拷贝到内核read buffer;
- 之后,DMA从内核read buffer将数据拷贝到网卡接口buffer上;
零拷贝的两次操作均不需要CPU参与。
Netty中的零拷贝体现在:
- bytebuffer;
- Composite Buffers;
- FileChannel.transferTo的使用;
参考自掘金大佬