Netty 核心组件

1. 前言

本节我们主要从整体上了解 Netty 有哪些核心组件,很多同学学习完 Netty 虽然会使用,但是只知道如何自定义 Handler 而已,根本不清楚 Netty 有哪些核心的组件。

本节的主要目的是,从整体上概括 Netty 的核心组件,有助于深入了解 Netty 以及关于 Netty 的面试。

2. 核心组件

Netty 的核心模块组件主要分为以下:

组件模块 说明
Boostrap Bootstrap 其实就是启动的意思,主要用来配置 Netty 的相关配置,串联各个组件,针对客户端。
ServerBootstrap 同上,只是它是针对服务端。
线程模型 了解 Reactor 线程模型。
EventLoopGroup 是一组 EventLoop 的抽象,可以简单理解就是线程池,一般分为 BossEventLoopGroup 和 WorkerEventLoopGroup。
ChannelFuture Netty 的所有 IO 操作都是异步的,通过注册监听器来监听执行结果的返回。
Channel Netty 的网络通信组件,客户端和服务端建立连接之后会维持一个 Channel。
ChannelHandlerContext 保存 Channel 对于的上下文,同时关联一个 ChannelHandler 对象。
ChannelHandler 自定义业务 Handler 需要实现它或它的子类,提供了一套生命周期的方法。
ChannelPipeline ChannelPipeline 可认为是一个管道,是管理业务 Handler,通俗理解是保存 ChannelHandler 的 List 集合。
ByteBuf ByteBuf 是一个字节容器,提供了常见 api。Netty 是面向 ByteBuf 来传输数据的。
编码和解码 Netty 内置了常见编解码器,我们也可以自定义自己的编解码器。并且可以把编解码器封装成独立的 Handler,简化繁琐的流程。
拆包和粘包问题 了解为什么会出现拆包和粘包问题,如何去解决它,以及 Netty 内置了常见的拆包器。

总结,以上组件(或者知识点)是 Netty 知识体系里面的核心,并且也是面试当中经常问的内容,有的只需要配置一下即可,很少需要我们去管(如:EventLoopGroup);有的需要我们去自定义扩展。

核心组件架构图:
图片描述

在真实开发当中,需要我们去解决的问题,主要如下:

  1. 使用 ChannelPipeline 管理自定义 ChannelHandler;
  2. 业务实体和 ByteBuf 之间的转换;
  3. 借助第三方序列化技术、自定义通信协议规则、反射等,自定义编码和解码器,使用通用实体;
  4. 如何解决拆包和粘包问题,其发生的原因是什么,如果解决。

3. 组件详解

Netty 的它优势在于,它是配置化的开发,仅仅靠简单的配置,背后就能实现很复杂的逻辑。但是通常情况下我们很难去了解其背后的原理。下面我们主要挑选开发当中比较常见的组件进行讲解。

3.1 ChannelHandler

ChannelHandler 是一个接口,处理 IO 事件,可以简单的理解它是一个链表当中的一个节点,它的 UML 图如下所示:
图片描述

ChannelHandler 架构图说明:

  1. ChannelHandler 两个子接口,分别是 ChannelInboundHandler 和 ChannelOutboundHandler;其中 ChannelInboundHandler 主要用于处理入站的 I/O 事件;ChannelOutboundHandler 用于处理出站的 I/O 事件;
  2. ChannelInboundHandler 的实现类 ChannelInboundHandlerAdapter 处理入站 I/O 事件;
  3. ChannelOutboundHandler 的实现类 ChannelOutboundHandlerAdapter 处理出站 I/O 事件;

在开发当中,ChannelInboundHandlerAdapter 是使用最多的,其它很少直接使用。值得注意的是 I/O 入站和出站的执行顺序,这个跟 SpringMVC 的拦截器的执行顺序一样。

3.2. ChannelPipeline

ChannelPipeline 是一个比较核心的知识点,它底层设计是采用责任链设计模式,主要作用是管理 Handler 双向链表,包括入站和出站,主要是拦截 inboud 和 outbound 事件,然后每个 handler 节点负责处理具体逻辑。
图片描述

关系梳理:

  1. 一个客户端对应一个 Channel;
  2. 一个 Channel 对应一个 ChannelPipeline;
  3. 一个 ChannelPipeline 又维护了一个双向链表,其中链表的节点是 ChannelHandlerContext
  4. 一个 ChannelHandlerContext 则关联一个 ChannelHandler(自定义 Handler);
  5. ChannelHandler 则是自定义 Handler 的一个顶级抽象接口。

入站和出站的顺序:

  1. 入站: 事件会从链表的头部一直往后执行,ChannelInboundHandlerAdapter 子类会被触发;
  2. 出站: 事件会从链表的尾部一直往前执行,ChannelOutboundHandlerAdapter 子类会被触发。

4. 小结

本节内容,主要让大家从整体上了解 Netty 有哪些核心的组件构成,每个主要的作用是什么,主要是方便后面章节深入学习。其中,核心掌握 ChannelHandler 和 ChannelPipeline 这两个组件,平时开发当中涉及比较多的就是这两个组件。

  1. 掌握 ChannelHandler 的 UML 架构关系;
  2. 掌握入站和出站分别继承 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter;
  3. 掌握 ChannelPipeline 和 ChannelHandler 之间的关系;
  4. 掌握入站和出站的执行顺序。