0%

Netty

NIO

  1. 三大核心:Channel(通道)、Buffer(缓冲区)、Selector(选择器)

原生NIO存在的问题

  1. NIO的类库和API繁琐,使用麻烦:需要熟练掌握Selector、ServerSocketChannel、ServerSocket、ByteBuffer等。
  2. 需要具备其他的额外技能:要熟悉 Java 多线程编程,因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网络编程非常熟悉,才能编写出高质量的 NIO 程序。
  3. 开发工作量和难度都非常大:例如客户端面临断线重连、网络闪断、半包读写、失败缓存、网络堵塞和异常流的处理等等。
  4. JDK NIO 的 Bug:例如臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%。直到 JDK 1.7 版本该问题仍旧存在,没有被根本解决。

线程模型

单 Reactor 模式

单 Reactor 单线程

NIO 群聊

单 Reactor 多线程


优点:可以充分的利用多核cpu的处理能力。
缺点:多线程数据共享和访问比较复杂,reactor 处理所有的事件的监听和响应,在单线程运行,在高并发场景容易出现性能瓶颈。

主从 Reactor 多线程

  1. Reactor 主线程 MainReactor 对象通过 select 监听链接事件,收到时间后,通过 Acceptor 处理链接事件。
  2. 当 Acceptor 处理链接事件后,MainReactor 将连接分配给 SubReactor.
  3. subreactor 将连接加入到连接队列进行监听,并创建 handler 进行各种事件处理。
  4. 当有新事件发生时,subreactor 就会调用对应的 handler 处理。
  5. handler 通过 read 读取数据,分发给后面的 worker 线程处理。
  6. worker 线程池分配独立的 worker 线程进行业务处理,并返回结果。
  7. handler 收到响应的结果后,再通过 send 将结果返回给client。
  8. Reactor 主线程可以对应多个 Reactor 子线程,即 MainReactor 可以关联多个 subreactor

方案优缺点

优点:

  1. 父线程与子线程的数据交互简单职责明确,父线程只需要接收新连接,子线程完成后续的业务处理。
  2. 父线程与子线程的数据交互简单,Reactor 主线程只需要把新连接传给子线程,子线程无需返回数据。

缺点:

  1. 编程复杂度较高

结合实例:这种模型在许多项目中广泛使用,包括 Nginx 主从 Reactor 多进程模型,Memcached 主从多线程,Netty 主从多线程模型的支持。

Scalable IO in Java 书中作者 Doug Lea 对 Reactor 模型的理解

Netty 模型

工作原理示意图
工作原理示意图-解析

  1. Netty抽象出两组线程池BossGroup专门负责接收客户端的连接,WorkerGroup专门负责网络的读写。
  2. BossGroup和WorkerGroup类型都是NioEventLoopGroup
  3. NioEventLoopGroup相当于一个事件循环组,这个组中含有多个事件循环,每个事件循环是NioEventLoop
  4. NioEventLoop 表示一个不断循环的执行处理任务的线程,每个NioEventLoop都有一个selector,用于监听绑定在其上的socket的网络通讯
  5. NioEventLoopGroup 可以有多个线程,即可以含有多个NioEventLoop
  6. 每个Boss NioEventLoop 执行的步骤有3步:
    1. 轮询accept事件
    2. 处理accept事件,与client建立连接,生成 NioSocketChannel,并将其注册到某个worker NIOEventLoop 上的selector
    3. 处理任务队列的任务,即 runAllTasks
  7. 每个Worker NIOEventLoop 循环执行的步骤
    1. 轮询read,write事件
    2. 处理i/o事件,即read,write事件,在对应 NioSocketChannel 处理
    3. 处理任务队列的任务,即 runAllTasks
  8. 每个Worker NIOEventLoop 处理业务时,会使用pipeline(管道),pipeline 中包含了 channel,即通过pipeline 可以获取到对应通道,管道中维护了很多的处理器。

Protobuf

http + json -> tcp + protobuf
Protobuf优点:

  1. 序列化后体积相比Json和XML很小,适合网络传输
  2. 支持跨平台多语言
  3. 消息格式升级和兼容性还不错
  4. 序列化反序列化速度很快,快于Json的处理速速

Protobuf缺点:

  1. 二进制格式导致可读性差
  2. 缺乏自描述
  3. 通用性差

文档

Handler

  1. 不论解码器handler还是编码器handler,接收的消息类型必须与待处理的消息类型一致,否则该handler不会被执行
  2. 在解码器进行数据解码时,需要判断缓存区(ByteBuf)的数据是否足够,否则接收到的结果与期望结果可能不一致

语言指南

参考资料

课件
笔记
https://cloud.tencent.com/developer/article/1754078