上一篇文章中,我们介绍了ServerBootstrap的启动过程,在这个过程中引出了一个很重要的类ChannelPipeline。如果说内存池,线程模型是netty的基础,我们接触的相对来说并不是那么直接,那么ChannelPipeline则是我们开发中直接能够接触到的概念,如果对其不了解,很容易造成一些不正确的使用姿势或一些然并卵的优化。现在我们就来看看ChannelPipeline的作用到底是啥。
ChannelPipeline包含了一个ChannelHander形成的列表。其中ChannelHander是用于处理连接的Inbound或者Outbound事件,也是所有开发者都会直接接触到的一个类。ChannelPipeline实现了一个比较高级的拦截过滤模式,用户可以完全控制事件的处理,并且pipeline中的ChannelHandler可以相互交互。
不管是server还是client,每个连接都会对应一个pipeline,该pipeline在Channel被创建的时候创建(注意这里的Channel是指netty中封装的Channel,而不是jdk的底层连接)。先看看ChannelPipeline的官方注释,(比较懒,直接截了个图。。。),该注释直观的描述了IO事件在pipeline中的处理流程。
从图中可以看到inbound事件(read为代表)是从ChannelHandler1开始处理一直到最后一个ChannelHandler N,而outbound事件(write为代表)则是从ChannelHandler N开始处理,一直到ChannelHandler1。当然这个只是一个典型的处理流程,用户可以完全控制这个流程,改变事件的处理流程,如跳过其中一个ChannelHander,甚至在处理过程中动态的添加或者删除ChannelHandler。那么inbound和outbound各自有哪些事件呢?来看看下面两个表:
方法 | 对应事件 |
---|---|
ChannelHandlerContext#fireChannelRegistered() | 注册连接 |
ChannelHandlerContext#fireChannelUnregistered() | 取消注册 |
ChannelHandlerContext#fireChannelActive() | 连接激活 |
ChannelHandlerContext#fireChannelRead(Object) | 读取数据 |
ChannelHandlerContext#fireChannelReadComplete() | 读取完成 |
ChannelHandlerContext#fireExceptionCaught(Throwable) | 发生异常 |
ChannelHandlerContext#fireUserEventTriggered(Object) | 用户事件触发 |
ChannelHandlerContext#fireChannelWritabilityChanged() | 可写状态改变 |
ChannelHandlerContext#fireChannelInactive() | 检测到连接断开 |
方法 | 对应事件 |
---|---|
ChannelHandlerContext#bind(SocketAddress, ChannelPromise) | 绑定端口 |
Channel |