Netty架构剖析

Netty逻辑架构

Netty采用了典型的三层网络架构进行设计和开发,如图:
Netty逻辑架构图

Reactor通信调度层

有一系列辅助类完成,包括Reactor线程NioEventLoop及其父类,NioSocketChannel/NioServerSocketChannel及其父类,ByteBuffer以及由其衍生出来的各种Buffer,Unsafe以及其衍生出的各种内部类等。该层的主要职责就是监听网络的读写和连接操作,负责将网络层的数据读取到内存缓冲区中,然后出发各种网络事件,例如连接创建、连接急活、读事件、写事件等,将这些事件出发到Pipeline中,有Pipeline管理的职责链来进行后续的处理。

职责链ChannelPipeline

负责事件在职责链中的有序传播,同时负责动态的编排职责链。职责链可以选择监听和处理自己关心的事件,它可以拦截处理和向后/向前传播事件。不同应用的Handler节点的功能也不同,通常情况下,往往会开发编解码Handler用于消息的编解码,它可以将外部的协议消息转换成内部的POJO对象,这样上层业务则只需要关系处理业务逻辑即可,不需要感知底层的协议差异和线程模型差异,实现了架构层面的分层隔离。

业务逻辑编排层(Service ChannelHandler)

业务逻辑编排层通常有两类:一类是 纯粹的业务逻辑编排,还有一类是其他的应用层协议插件,用于特定协议相关的会话和链路管理。例如CMPP协议,用于管理和中国移动短信系统的对接。
架构的不同层面,需要关心和处理的对象都不同,通常情况下,对于业务开发者,只需要关心职责链的拦截和业务Handler的编排。因为应用层协议栈往往是开发一次,到处运行,所以实际上对于业务开发者来说,只需要关心服务层的业务逻辑开发即可。各种应用协议以插件的形式提供,只有协议开发人员需要关注协议插件,对于其他业务开发人员来说,只需关系业务逻辑定制。这种分层架构设计理念实现了NIO框架各层之间的解耦,便于上层业务协议栈的开发和业务逻辑的定制。

Netty的高性能

  1. 采用异步非阻塞的I/O类库,基于Reactor模式实现,解决了传统同步阻塞I/O模式下一个服务端无法平滑地处理线性增长的客户端的问题。
  2. TCP接收和发送缓冲区使用直接内存代替堆内存,避免了内存复制,提升了I/O读取和写入的性能。
  3. 支持通过内存池的方式循环利用ByteBuf,避免了频繁创建和销毁ByteBuf带来的性能损耗
  4. 可配置的I/O线程数、TCP参数等,为不同的用户场景提供定制化的调优参数,满足不同的性能场景
  5. 采用环形数组缓冲区实现无锁化并发编程,代替传统的线程安全容器或者锁
  6. 合理地使用线程安全容器、原子类等,提升系统的并发处理能力
  7. 关键资源的处理使用单线程串行化的方式,避免多线程并发访问带来的锁竞争和额外的CPU资源消耗问题
  8. 通过引用计数器及时地申请释放不在被引用的对象,细粒度的内存管理降低了GC的频率,减少了频繁GC带来的时延增大和CPU损耗。

Netty的高可靠

  1. 链路有效性检测。利用心跳机制周期性地进行链路检测,Netty提供了两种链路空闲检测机制:
  • 读空闲超时机制:当连续周期T没有消息可读时,触发超时Handler,用户可以基于读空闲超时发送心跳消息,进行链路检测,如果连续N个周期仍然没有读取到心跳消息,可以主动关闭链路
  • 写空闲超时机制:当连续周期T没有消息要发送时,触发超时Handler,用户可以基于写空闲超时发送心跳消息,进行链路检测,如果连续N个周期仍然没有接收到对方的心跳消息,可以主动关闭链路
  1. 内存保护机制。包括以下几个方面:
  • 通过对象引用计数器对Netty的ByteBuf等内置对象进行细粒度的内存申请和释放,对非法的对象引用进行检测和保护
  • 通过内存池来重用ByteBuf,节省内存
  • 可设置的内存容量上限,包括ByteBuf、线程池线程数等
  1. 优雅停机。当系统退出时,JVM通过注册的ShutdownHook拦截到退出信号量,然后执行退出操作,释放相关模块的资源占用,将缓冲区的消息处理完成或者清空,将待刷新的数据持久化的磁盘或者数据库中,等到资源回收和缓冲区消息处理完成之后,再退出
  2. 可定制性。主要体现在一下几点:
  • 责任链模式:ChannelPipeline基于责任链模式开发,便于业务逻辑的拦截、定时和扩展
  • 基于接口的开发:关键的类库都提供了接口或者抽象类,如果Netty自身的实现无法满足用户的需求,可以由用户自定义实现相关接口
  • 提供了大量工厂类,通过重载这些工厂类可以按需创建出用户实现的对象
  • 提供了大量的系统参数供用户按需设置,增强系统的场景定制性
  1. 可扩展性。基于Netty的基础NIO框架,可以方便地进行应用层协议定制,例如HTTP协议栈、Thrift协议栈、FTP协议栈等。这些扩展不需要修改Netty的源码,直接基于Netty的二进制类库即可实现协议的扩展和定制。
评论