Netty 框架学习 —— Netty 组件与设计
Channel、EventLoop 和 ChannelFuture
这一节将对 Channel、EventLoop 和 ChannelFuture 类进行讨论,它们组合在一起,可以被认为是 Netty 网络抽象的代表:
- Channel —— Socket
- EventLoop —— 控制流、多线程处理、并发
- CHannelFuture —— 异步通知
1. Channel 接口
Netty 的 Channel 接口对应 Java 网络编程的 Socket,大大降低了直接使用 Socket 类的复杂性。此外,Channel 也拥有其他预定义的实现类:
- EmbeddedChannel:测试 ChannelHandler
- LocalServerChannel:用于同一个 JVM 内部实现 client 和 server 之间的通信
- NioSocketChannel:异步的客户端 TCP Socket 连接
- NioServerSocketChannel:异步的服务器端 TCP Socket 连接
- NioDatagramChannel:异步的 UDP 连接
- NioSctpChannel:异步的客户端 Sctp 连接
- NioSctpServerChannel:异步的 Sctp 服务器端连接
- OioSocketChannel:同步的客户端 TCP Socket 连接
- OioServerSocketChannel:同步的服务器端 TCP Socket 连接
- OioDatagramChannel:同步的 UDP 连接
- OioSctpChannel:同步的 Sctp 服务器端连接
- OioSctpServerChannel:同步的客户端 TCP Socket 连接
2. EventLoop 接口
EventLoop 用于处理连接的生命周期中所发生的事件,下图说明了 Channel、EventLoop、Thread 以及 EventLoopGroup 之间的关系

这些关系是:
- 一个 EventLoopGroup 包含一个或多个 EventLoop
- 一个 EventLoop 在它的生命周期内只和一个 Thread 绑定
- 所有由 EventLoop 处理的 IO 事件都将在它专有的 Thread 上被处理
- 一个 Channel 在它的生命周期内只注册一个 EventLoop
- 一个 EventLoop 可能会被分配到一个或多个 Channel
3. ChannelFuture 接口
Netty 所有的 IO 操作都是异步的,一个操作可能不会立即返回结果,因此我们需要一种用于在之后的某个时间点确定其结果的方法。Netty 提供了 ChannelFuture 接口,其 addListener() 方法注册一个 ChannelFutureListener,以便在某个操作完成时(无论是否成功0得到通知)
ChannelHandler 和 ChannelPipeline
1. ChannelHandler 接口
ChannelHandler 可以看作是负责处理入站和出站数据的应用程序逻辑的容器,例如将数据从一个格式转换为另一种格式,处理抛出的异常等等。ChannelInboundHandler 是一个经常使用的子接口,这种类型的 ChannelHandler 接收入站事件和数据,这些数据随后将被你的业务逻辑锁处理。当你想要给客户端发送响应时,也可以从 ChannelInboundHandler 冲刷数据,通常应用程序的业务逻辑通常驻留在一个或者多个 ChannelInboundHandler 中
2. ChannelPipeline 接口
ChannelPipeline 为 ChannelHandler 链提供了容器,并定义了用于在该链上传播入站和出站事件流的 API。当 Channel 被创建时,它会被自动地分配到它专属的 ChannelPipeline
ChannelHandler 安装到 ChannelPipeline 中的过程如下所示:
- 一个 ChannelInitializer 的实现被注册到了 ServerBootstrap 中
- 当 ChannelInitializer.initChannel() 方法被调用时,ChannelInitializer 将在 ChannelPipeline 中安装一组自定义的 ChannelHandler
- ChannelInitializer 将它自己从 ChannelPipeline 中移除
ChannelHandler 可以看作是处理往来 ChannelPipeline 事件(包括数据)的任何代码的通用容器,使事件流经过 ChannelPipeline 是 ChannelHandler 的工作,在应用程序的初始化或者引导阶段被安装。这些 ChannelHandler 接收事件、执行所实现的业务逻辑,并将数据传递给链中的下一个 ChannelHandler。它们的执行顺序由它们被添加的顺序所决定。实际上,ChannelPipeline 就是这些 ChannelHandler 的编排顺序
当 ChannelHandler 被添加到 ChannelPipeline 时,它会被分配一个 ChannelHandlerContext,其代表了 ChannelHandler 和 ChannelPipeline 之间的绑定,虽然这个对象可以被用于获取底层的 Channel,但它还是主要用于写出站数据
在 Netty 中有两种发送消息的方式,可以直接写到 Channel 中,也可以写到和 ChannelHandler 相关联的 ChannelHandlerContext 对象中。前一种方式将会导致消息从 ChannelPipeline 的尾端开始流动,后者将导致消息从 ChannelPipeline 中的下一个 ChannelHandler 开始流动
编码器和解码器
当你通过 Netty 发送或者接收一个消息时,就会发生一次数据转换。入站消息会被解码,即从字节转换成另一种格式,通常是一个 Java 对象。如果是出站消息,则会发生相反方向的转换,从当前格式被编码为字节。为此,Netty 为编码器和解码器提供了不同类型的抽象类,这些基类的名称将类似于 ByteToMessageDecoder 或 MessageToByteEncoder。对于一些特殊类型,可能还会有 ProtobufEncoder 和 ProtobufDecoder 这样的名称,用来支持 Google 的 Protocol Buffers
使用 Netty 提供的编码器/解码器,你会发现对于入站数据来说,channelRead 方法/事件已经被重写。对于每个从入站 Channel 读取的消息,将调用重写后的 channelRead 方法。随后,它将调用解码器提供的 decode() 方法,将已解码的字节转发给 ChannelPipeline 中的下一个 ChannelInboundHandler。出站消息是反过来的,编码器将消息转换为字节,并将它们转发给下一个 ChannelOutboundHandler
引导
Netty 的引导类为应用程序的网络层配置提供了容器,这涉及将一个进程绑定到某个指定的端口,或者将一个进程连接到另一个运行在某个指定主机的指定端口上的进程。通常我们把前面的用例称为引导一个服务器,后面的用例称为引导一个客户端。因此,有两种类型的引导:一种用于客户端(Bootstrap),而另一种(ServerBootstrap)用于服务器
两种类型的引导类区别如下:
ServerBootstrap 将绑定到一个端口,因为服务器必须要监听连接,而 Bootstrap 则是由想要连接到远程节点的客户端应用程序使用
引导一个客户端只需要一个 EventLoopGroup,但是一个 ServerBootstrap 则需要两个。因为服务器需要两组不同的 Channel,第一组只包含一个 ServerChannel,代表服务器自身已绑定到某个本地端口的正在监听的套接字,而第二组将包含所有已创建的用来处理传入客户端连接的 Channel
与 ServerChannel 相关联的 EventLoopGroup 将分配一个负责为传入连接请求创建 Channel 的 EventLoop。一旦连接被接受,第二个 EventLoopGroup 就会给它的 Channel 分配一个 EventLoop
Netty 框架学习 —— Netty 组件与设计的更多相关文章
- NetCore Netty 框架 BT.Netty.RPC 系列随讲 二 WHO AM I 之 NETTY/NETTY 与 网络通讯 IO 模型之关系?
一:NETTY 是什么? Netty 是什么? 这个问题其实百度上一搜一堆. 这是官方话的描述:Netty 是一个基于NIO的客户.服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个 ...
- Netty 框架学习 —— 引导
概述 前面我们学习了 ChannelPipeline.ChannelHandler 和 EventLoop 之后,接下来的问题是:如何将它们组织起来,成为一个可实际运行的应用程序呢?答案是使用引导(B ...
- Netty 框架学习 —— 编解码器框架
编解码器 每个网络应用程序都必须定义如何解析在两个节点之间来回传输的原始字节,以及如何将其和目标应用程序的数据格式做相互转换.这种转换逻辑由编解码器处理,编解码器由编码器和解码器组成,它们每种都可以将 ...
- Netty 框架学习 —— 第一个 Netty 应用
概述 在本文,我们将编写一个基于 Netty 实现的客户端和服务端应用程序,相信通过学习该示例,一定能更全面的理解 Netty API 该图展示的是多个客户端同时连接到一台服务器.客户端建立一个连接后 ...
- Netty 框架学习 —— EventLoop 和线程模型
EventLoop 接口 Netty 是基于 Java NIO 的,因此 Channel 也有其生命周期,处理一个连接在其生命周期内发生的事件是所有网络框架的基本功能.通常来说,我们使用一个线程来处理 ...
- Netty 框架学习 —— ByteBuf
概述 网络数据的基本单位总是字节,Java NIO 提供了 ByteBuffer 作为它的字节容器,但这个类的使用过于复杂.Netty 的 ByteBuf 具有卓越的功能性和灵活性,可以作为 Byte ...
- Netty 框架学习 —— 单元测试
EmbeddedChannel 概述 ChannelHandler 是 Netty 程序的关键元素,所以彻底地测试它们应该是你的开发过程中的一个标准部分,EmbeddedChannel 是 Netty ...
- Netty 框架学习 —— 预置的 ChannelHandler 和编解码器
Netty 为许多提供了许多预置的编解码器和处理器,几乎可以开箱即用,减少了在烦琐事务上话费的时间和精力 空闲的连接和超时 检测空闲连接以及超时对于释放资源来说至关重要,Netty 特地为它提供了几个 ...
- Netty 框架学习 —— 添加 WebSocket 支持
WebSocket 简介 WebSocket 协议是完全重新设计的协议,旨在为 Web 上的双向数据传输问题提供一个切实可行的解决方案,使得客户端和服务器之间可以在任意时刻传输消息 Netty 对于 ...
随机推荐
- Parentheses Balance UVA - 673
You are given a string consisting of parentheses () and []. A string of this type is said to be corr ...
- Score UVA - 1585
There is an objective test result such as "OOXXOXXOOO". An 'O' means a correct answer of ...
- 1016 Phone Bills
A long-distance telephone company charges its customers by the following rules: Making a long-distan ...
- Python小游戏 -- 猜单词
Python初学者小游戏:猜单词 游戏逻辑:就像我们曾经英语学习机上的小游戏一样,电脑会从事先预置的词库中抽取单词,然后给出单词的字母数量,给定猜解次数,然后让玩家进行猜测,并给出每次猜测的正确字母与 ...
- DVWA之SQL注入考点小结
SQL Injection SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害是巨大的,常常 ...
- Windows PE导出表编程4(重构导出表实现私有函数导出)
本次是尝试调用DLL里面的私有函数. 一: 之前先探索一下,首先可以考虑用偏移量来调用,就是如果知道了某个私有函数和某个导出的公共函数的相对便宜的话,直接加载dll获取公共函数地址,然后自己手动去偏移 ...
- Day003 +和字符串使用的问题
先看一段代码 int a=10; int b=20; System.out.println(""+a+b); System.out.println(a+b+"" ...
- layui框架下如何给select的option选项赋值
后端返回数据格式 axios方法执行成功后返回的数据格式如下图 前端下拉框 <div class="layui-form-item"> <label class= ...
- SwiftUI 简明教程之指示器
本文为 Eul 样章,如果您喜欢,请移步 AppStore/Eul 查看更多内容. Eul 是一款 SwiftUI & Combine 教程 App(iOS.macOS),以文章(文字.图片. ...
- MySQL库表设计小技巧
前言: 在我们项目开发中,数据库及表的设计可以说是非常重要,我遇到过很多库表设计比较杂乱的项目,像表名.字段名命名混乱.字段类型设计混乱等等,此类数据库后续极难维护与拓展.我一直相信只有优秀的库表设计 ...