Netty底层原理

本文详细介绍了Netty的线程模型、多路复用器的应用、解码编码策略,包括序列化方法(如Protobuf和JSON)以及零拷贝优化。同时讨论了背压概念在流量控制中的作用,特别是在冷Observable和hotObservable场景的应用。

NIO有一个非常重要的组件——多路复用器,其底层有3种经典模型,分别是epoll、select和poll。与传统IO相比,一个多路复用器可以处理多个Socket连接,而传统IO对每个连接都需要一条线程去同步阻塞处理。NIO有了多路复用器后只需要一条线程即可管理多个Socket连接的接入和读写事件。

Netty的多路复用器默认调用的模型是epoll模型,它除了JDK自带的epoll模型的封装,还额外封装了一套,这两者都是epoll模型的封装,只是JDK的epoll模型是水平触发的,而Netty采用JNI重写的边缘触发。

一、线程模型

对于服务器端而言有两个线程组,Boss线程组和Worker线程组。其中Boss线程组一般只开启一条线程(除非一个Netty服务同时监听多个端口),Worker线程数默认是CPU核数的两倍。Boss线程主要监听SocketChannel的OP_ACCEPT事件和客户端的连接。

**当Boss线程监听到有SocketChannel连接接入时,会把SocketChannel包装成NioSocketChannel,并注册到Worker线程的Selector中,同时监听其OP_WRITE和OP_READ事件。**当Worker线程监听到某个SocketChannel有就绪的读IO事件时,就会进行以下操作:

  1. 向内存池中分配内存,读取IO数据流
  2. 将读取后的ByteBuf传递给解码器Handler进行解码,若能解码出完整的请求数据包,就会把请求数据包交给业务逻辑处理Handler
  3. 经过业务逻辑处理Handler后,在返回响应结果前,交给编码器进行数据加工
  4. 最终写到缓冲区,并由IO Worker线程将缓冲区的数据输出到网络中并传输给客户端

二、解码和编码

使用Java NIO来实现TCP网络通讯,需要对TCP连接中的问题进行进行全面的考虑,如拆包和粘包导致的半包问题和序列化等。对于这些问题,Netty都进行了很好的处理。

客户端给服务端发送消息并受到服务端返回的结果共经历了以下6步:

  1. TCP是面向字节流传输的协议,它把客户端提交的请求数据看作一连串的无结构的字节流,并不知道所传送的字节流的含义,也并不关心有多少数据流入TCP输出缓冲区中

  2. **每次发多少数据到网络中与当前网络的拥塞情况和服务端返回的TCP窗口的大小有关,涉及TCP的流量控制和拥塞控制,并且与Netty的反压有关。**如果客户端发送到TCP输出缓冲区的数据块太多,那么TCP会分割成多次将其传送出去,如果太少,则会等待积累足够多的字节后发送出去。很明显TCP这种传输机制会产生粘包问题

  3. 当服务端读取TCP输入缓冲区中的数据时,需要进行拆包处理,并解决粘包和拆包的问题,比较常见的方案有以下3种:

    1. 将换行符号或特殊标识符号加入数据包中,如HTTP和FTP等(LineBasedFrameDecoder)
    2. 将消息分为head和body,head中包含body长度的字段, 一般前面4个字节是body的长度值,用int表示,但也有像Dubb
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

得过且过的勇者y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值