最新要闻
- 上市公司实控人离婚140亿归女方,盘点彤程新材投资版图
- 千元神机!荣耀X50首发骁龙6 Gen1:一亿像素加持
- 育碧再次背离玩家!《刺客信条:幻景》PC端Steam独不占_世界百事通
- 一眼假的诈骗短信是骗子智商不够吗?官方:这是极高效率筛选受害者
- 京东618大促攻略:iPhone 14 Pro系列直降1800元 多会员年卡探底|环球视点
- 百度文心大模型3.5版要来了!李彦宏:大模型将改变世界 环球热门
- 屹通新材:5月25日融资买入167.73万元,融资融券余额3877.74万元
- 一天斩获3个冠军!全国花游冠军赛北京队“开门红”-快看点
- DXO拍照全球第一!华为P60 Pro新增12GB+256GB版本 6488元
- 单价6.5亿 想坐吗?国产大飞机C919商业首航来了:5月28日、上海至北京_微头条
- 神操作 小汽车撞倒闯红灯三轮车后居然直接走了 无责变有责
- 糟糕!下一轮国内油价调整“由跌转涨”:当前上调75元/吨 今日快讯
- 牌面!福特CEO称特斯拉不是最大竞争对手 比亚迪才是 环球新消息
- 焦点要闻:美联储加息预期升温 美元兑日元汇率再度站上140
- 计算机时代变了 NVIDIA黄仁勋:CPU用得越来越少 GPU才是关键|世界实时
- 【世界快播报】自研火箭发射8颗卫星 韩国表态已成航天强国:仅中美等7国做到
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
Netty实战(三)
一、Channel、EventLoop 和 ChannelFuture
上一篇博文我们在构建服务端和客户端中出现了一些新的类,可能有些同学还有些不了解它们的具体功能。没关系,接下来我们对于 Channel、EventLoop 和 ChannelFuture 类进行的讨论增添更多的细节,这些类合在一起,可以被认为是 Netty 网络抽象的代表:
- Channel : Socket;
- EventLoop : 控制流、多线程处理、并发;
- ChannelFuture : 异步通知。
1.1 Channel 接口
基本的 I/O 操作(bind()、connect()、read()和 write())依赖于底层网络传输所提供的原语。在基于 Java 的网络编程中,其基本的构造是 class Socket。Netty 的 Channel 接口所提供的 API,大大地降低了直接使用 Socket 类的复杂性。此外,Channel 也是拥有许多预定义的、专门化实现的广泛类层次结构的根,下面是一个简短的部分清单:
- EmbeddedChannel;
- LocalServerChannel;
- NioDatagramChannel;
- NioSctpChannel;
- NioSocketChannel。
1.2 EventLoop 接口
EventLoop 定义了 Netty 的核心抽象,用于处理连接的生命周期中所发生的事件。如图在高层次上说明了 Channel、EventLoop、Thread 以及 EventLoopGroup 之间的关系。
(资料图)
这些关系可以表述为:
- 一个 EventLoopGroup 包含一个或者多个 EventLoop;
- 一个 EventLoop 在它的生命周期内只和一个 Thread 绑定;
- 所有由 EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理;
- 一个 Channel 在它的生命周期内只注册于一个 EventLoop;
- 一个 EventLoop 可能会被分配给一个或多个 Channel。
注意,在这种设计中,一个给定 Channel 的 I/O 操作都是由相同的 Thread 执行的,实际上消除了对于同步的需要。
1.3 ChannelFuture 接口
Netty 中所有的 I/O 操作都是异步的。因为一个操作可能不会立即返回,所以我们需要一种用于在之后的某个时间点确定其结果的方法。为此,Netty 提供了ChannelFuture 接口,其 addListener()方法注册了一个ChannelFutureListener,以便在某个操作完成时(无论是否成功)得到通知。
可以将 ChannelFuture 看作是将来要执行的操作的结果的占位符。它究竟什么时候被执行则可能取决于若干的因素,因此不可能准确地预测,但是可以肯定的是它将会被执行。此外,所有属于同一个 Channel 的操作都被保证其将以它们被调用的顺序被执行。
二、ChannelHandler 和 ChannelPipeline
2.1 ChannelHandler 接口
从应用程序开发人员的角度来看,Netty 的主要组件是 ChannelHandler,它充当了所有处理入站和出站数据的应用程序逻辑的容器。这是可行的,因为 ChannelHandler 的方法是由网络事件(其中术语“事件”的使用非常广泛)触发的。事实上,ChannelHandler 可专门用于几乎任何类型的动作,例如将数据从一种格式转换为另外一种格式,或者处理转换过程中所抛出的异常。
举例来说,ChannelInboundHandler 是一个我们会经常实现的子接口。这种类型的ChannelHandler 接收入站事件和数据,这些数据随后将会被我们的应用程序的业务逻辑所处理。当我们要给连接的客户端发送响应时,也可以从 ChannelInboundHandler 冲刷数据。我们的应用程序的业务逻辑通常驻留在一个或者多个 ChannelInboundHandler 中。
Netty 以适配器类的形式提供了大量默认的 ChannelHandler 实现,其旨在简化应用程序处理逻辑的开发过程。如ChannelPipeline中的每个ChannelHandler将负责把事件转发到链中的下一个 ChannelHandler。这些适配器类(及它们的子类)将自动执行这个操作,所以我们只重写那些你想要特殊处理的方法和事件。
那么为什么要用适配器的形式提供这些?
那是因为有一些适配器类可以将编写自定义的 ChannelHandler 所需要的努力降到最低限度,因为它们提供了定义在对应接口中的所有方法的默认实现。下面这些是编写自定义 ChannelHandler 时经常会用到的适配器类:
- ChannelHandlerAdapter
- ChannelInboundHandlerAdapter
- ChannelOutboundHandlerAdapter
- ChannelDuplexHandler
2.2 ChannelPipeline 接口
ChannelPipeline 提供了 ChannelHandler 链的容器,并定义了用于在该链上传播入站和出站事件流的 API。当 Channel 被创建时,它会被自动地分配到它专属的 ChannelPipeline。ChannelHandler 安装到 ChannelPipeline 中的过程如下所示:
- 一个ChannelInitializer的实现被注册到了ServerBootstrap中或用于客户端的Bootstrap
- 当 ChannelInitializer.initChannel()方法被调用时,ChannelInitializer将在 ChannelPipeline 中安装一组自定义的 ChannelHandler;
- ChannelInitializer 将它自己从 ChannelPipeline 中移除。
为了审查发送或者接收数据时将会发生什么,让我们来更加深入地研究 ChannelPipeline和 ChannelHandler 之间的共生关系吧。
ChannelHandler 是专为支持广泛的用途而设计的,可以将它看作是处理往来 ChannelPipeline 事件(包括数据)的任何代码的通用容器。如图,其展示了从 ChannelHandler 派生的 ChannelInboundHandler 和ChannelOutboundHandler 接口。使得事件流经 ChannelPipeline 是 ChannelHandler 的工作,它们是在应用程序的初始化或者引导阶段被安装的。这些对象接收事件、执行它们所实现的处理逻辑,并将数据传递给链中的下一个 ChannelHandler(有点类似责任链模式)。它们的执行顺序是由它们被添加的顺序所决定的。实际上,被我们称为 ChannelPipeline 的是这些 ChannelHandler 的编排顺序。
如图,说明了一个 Netty 应用程序中入站和出站数据流之间的区别。从一个客户端应用程序的角度来看,如果事件的运动方向是从客户端到服务器端,那么我们称这些事件为出站的,反之则称为入站的。从上图看入站和出站 ChannelHandler 可以被安装到同一个 ChannelPipeline中。如果一个消息或者任何其他的入站事件被读取,那么它会从 ChannelPipeline 的头部开始流动,并被传递给第一个 ChannelInboundHandler。这个 ChannelHandler 不一定会实际地修改数据,具体取决于它的具体功能,在这之后,数据将会被传递给链中的下一个ChannelInboundHandler。最终,数据将会到达 ChannelPipeline 的尾端,届时,所有处理就都结束了。
数据的出站运动(即正在被写的数据)在概念上也是一样的。在这种情况下,数据将从ChannelOutboundHandler 链的尾端开始流动,直到它到达链的头部为止。在这之后,出站数据将会到达网络传输层,这里显示为 Socket。通常情况下,这将触发一个写操作。
ps:通过使用作为参数传递到每个方法的 ChannelHandlerContext事件可以被传递给当前ChannelHandler 链中的下一个ChannelHandler。因为你有时会忽略那些不感兴趣的事件,所以 Netty提供了抽象基类 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter。 ChannelHandlerContext 上的对应方法,每个都提供了简单地将事件传递给下一ChannelHandler的方法的实现。随后,你可以通过重写你所感兴趣的那些方法来扩展这些类。
上图中出站和入站的ChannelHandler都在同一个ChannelPipeline中,那么ChannelPipeline是如何区分和处理这两种不同的类别的呢?
虽然 ChannelInboundHandle 和ChannelOutboundHandle 都扩展自 ChannelHandler,但是 Netty 能区分 ChannelInboundHandler 实现和 ChannelOutboundHandler 实现,并确保数据只会在具有相同定向类型的两个 ChannelHandler 之间传递。
当ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandlerContext,其代表了 ChannelHandler 和 ChannelPipeline 之间的绑定。虽然这个对象可以被用于获取底层的 Channel,但是它主要还是被用于写出站数据。
在 Netty 中,有两种发送消息的方式。我们可以直接写到 Channel 中,也可以 写到和 ChannelHandler相关联的ChannelHandlerContext对象中。前一种方式将会导致消息从ChannelPipeline 的尾端开始流动,而后者将导致消息从 ChannelPipeline 中的下一个 ChannelHandler 开始流动。
总结一下:
- 将消息写入Channel 它将从尾端开始流动。
- 将消息写入ChannelHandler中,它将会从下一个ChannelHandler开始流动。
2.3 编码器和解码器
当我们通过 Netty 发送或者接收一个消息的时候,就将会发生一次数据转换。入站消息会被解码;也就是说,从字节转换为另一种格式,通常是一个 Java 对象。如果是出站消息,则会发生相反方向的转换:它将从它的当前格式被编码为字节。这两种方向的转换的原因很简单:网络数据总是一系列的字节。(编解码)
对应于特定的需要,Netty 为编码器和解码器提供了不同类型的抽象类。例如,我们的应用程序可能使用了一种中间格式,而不需要立即将消息转换成字节。我们将仍然需要一个编码器,但是它将派生自一个不同的超类。为了确定合适的编码器类型,我们可以应用一个简单的命名约定。通常来说,这些基类的名称将类似于 ByteToMessageDecoder 或 MessageToByteEncoder。对于特殊的类型,我们会发现类似于 ProtobufEncoder 和 ProtobufDecoder这样的名称——预置的用来支持 Google 的 Protocol Buffers。
严格地说,其他的处理器也可以完成编码器和解码器的功能。但是,正如有用来简化ChannelHandler 的创建的适配器类一样,所有由 Netty 提供的编码器/解码器适配器类都实现了 ChannelOutboundHandler 或者 ChannelInboundHandler 接口。
我们会发现对于入站数据来说,channelRead 方法/事件已经被重写了。对于每个从入站Channel 读取的消息,这个方法都将会被调用。随后,它将调用由预置解码器所提供的 decode()方法,并将已解码的字节转发给 ChannelPipeline 中的下一个 ChannelInboundHandler。出站消息的模式是相反方向的:编码器将消息转换为字节,并将它们转发给下一个ChannelOutboundHandler。
2.4 抽象类 SimpleChannelInboundHandler
最常见的情况是,你的应用程序会利用一个 ChannelHandler 来接收解码消息,并对该数据应用业务逻辑。要创建一个这样的 ChannelHandler,我们只需要扩展基类 SimpleChannelInboundHandler
在这种类型的 ChannelHandler 中,最重要的方法是 channelRead0(ChannelHandlerContext,T)。除了要求不要阻塞当前的 I/O 线程之外,其具体实现完全取决于我们。
三、引导
Netty 的引导类为应用程序的网络层配置提供了容器,这涉及将一个进程绑定到某个指定的端口(服务端),或者将一个进程连接到另一个运行在某个指定主机的指定端口上的进程(客户端)。
严格来说,“连接”这个术语仅适用于面向连接的协议,如 TCP,其保证了两个连接端点之间消息的有序传递。
因此,有两种类型的引导:一种用于客户端(简单地称为 Bootstrap),而另一种(ServerBootstrap)用于服务器。无论我们的应用程序使用哪种协议或者处理哪种类型的数据,唯一决定它使用哪种引导类的是它是作为一个客户端还是作为一个服务器(后面我们会单独开出一篇来写引导,它很重要)。
类别 | Bootstrap | ServerBootstrap |
---|---|---|
网络编程中的作用 | 连接到远程主机和端口 | 绑定到一个本地端口 |
EventLoopGroup 的数目 | 1 | 2 |
ps:实际上,ServerBootstrap 类也可以只使用一个 EventLoopGroup,此时其将在两个场景下共用同一个 EventLoopGroup。
细心的同学应该发现了,ServerBootstrap使用了2个EventLoopGroup,这是因为服务器需要两组不同的 Channel。
- 第一组将只包含一个 ServerChannel,代表服务器自身的已绑定到某个本地端口的正在监听的套接字。(专门用来创建Channel )
- 而第二组将包含所有已创建的用来处理传入客户端连接(对于每个服务器已经接受的连接都有一个)的 Channel。(专门为Channel分配EventLoop)
它们的关系如图:ServerChannel 相关联的 EventLoopGroup 将分配一个负责为传入连接请求创建Channel 的 EventLoop。一旦连接被接受,第二个 EventLoopGroup 就会给它的 Channel分配一个 EventLoop。
关键词:
Netty实战(三)
上市公司实控人离婚140亿归女方,盘点彤程新材投资版图
千元神机!荣耀X50首发骁龙6 Gen1:一亿像素加持
育碧再次背离玩家!《刺客信条:幻景》PC端Steam独不占_世界百事通
一眼假的诈骗短信是骗子智商不够吗?官方:这是极高效率筛选受害者
京东618大促攻略:iPhone 14 Pro系列直降1800元 多会员年卡探底|环球视点
百度文心大模型3.5版要来了!李彦宏:大模型将改变世界 环球热门
屹通新材:5月25日融资买入167.73万元,融资融券余额3877.74万元
统信UOS系统开发笔记(一):国产统信UOS系统搭建开发环境之虚拟机安装
揭秘百度IM消息中台的全量用户消息推送技术改造实践
Python工具箱系列(三十三)
海内外直播源码加密技术保障您的隐私安全 焦点快播
Windows下使用docker部署.Net Core 全球今热点
一天斩获3个冠军!全国花游冠军赛北京队“开门红”-快看点
DXO拍照全球第一!华为P60 Pro新增12GB+256GB版本 6488元
单价6.5亿 想坐吗?国产大飞机C919商业首航来了:5月28日、上海至北京_微头条
神操作 小汽车撞倒闯红灯三轮车后居然直接走了 无责变有责
糟糕!下一轮国内油价调整“由跌转涨”:当前上调75元/吨 今日快讯
牌面!福特CEO称特斯拉不是最大竞争对手 比亚迪才是 环球新消息
环球视讯!UE/虚幻 蓝图实现通过http获取数据(以高德地图API为例)&Json格式数据的读取
标准化考场时间同步系统(网络时钟系统)规划建设应用 每日快播
Java设计模式-策略模式|环球快资讯
焦点要闻:美联储加息预期升温 美元兑日元汇率再度站上140
计算机时代变了 NVIDIA黄仁勋:CPU用得越来越少 GPU才是关键|世界实时
【世界快播报】自研火箭发射8颗卫星 韩国表态已成航天强国:仅中美等7国做到
当前快报:跟比亚迪海豚争场子 五菱云朵8月上市:10万级大五座纯电新宠
焦点观察:优派推出新款27寸4K Mini LED显示器:支持96W反向充 2999元
山东一高速现天价救援费:20公里被收11000元 结局大快人心 观天下
世界热点!Fastjson 很快,但不适合我....
每日观点:干瘦肉炒什么配菜好吃?
一季度垃圾短信投诉5万件 官方揭秘:主要是这10家公司发的
18888元求票 五月天黄牛票涨回去了?29名黄牛被查处|当前简讯
你吃过没?商家回应淄博烧烤降温:再不降温我们也受不了|新消息
世界消息!成都一轿车冲进店铺撞坏16个骨灰盒 现场损坏严重:网友称是大众
遥遥领先!华为分布式存储斩获IO500榜全球第一:Intel看不见尾灯
裘皮是什么皮_裘皮的介绍 天天资讯
触达债务上限日期或在两周后 美债收益率延续上行_环球微头条
国际金融市场早知道:5月26日|焦点热讯
刘强东14年为宿迁投入超200亿!宿迁第一高楼启用 未来3年在当地新招上万人
世界热点评!《英雄联盟手游》今日更新:无限火力升级归来 英雄可达25级
刷新世界纪录!中国吊起142米、3068吨“巨无霸”大塔
选择商品的发布类目方式有_选择一款正确发布的商品
今日要闻!学系统集成项目管理工程师(中项)系列27_10大管理47过程、输入输出工具和技术(2版教材)
今天国内上映!《小美人鱼》来了 口碑解禁观众爱看小黑美人鱼
新概念英语语法词汇练习第一册_关于新概念英语语法词汇练习第一册简介 热点在线
调优圣经:零基础精通Jmeter分布式压测,10Wqps+超高并发 世界快资讯
直接用中文写提示词的Stable Diffusion扩展:sd-prompt-translator发布
上海高架斗气车主或涉嫌什么罪名?专家解读多种可能
天天热门:史上最大涨幅!康宁:所有玻璃基板提价20%
天天头条:让友商恨得牙痒痒的比亚迪宋Pro DM-i冠军版:到底怎么样?
视焦点讯!马斯克吹了三年的锂电之光4680:竟然还不如普通电池!
袋鼠贵为澳大利亚国宝 却每年被合法猎杀几百万只:为啥? 全球即时看
当前快播:宠物经济板块5月25日跌0.66%,狮头股份领跌,主力资金净流出7407.47万元
鼻中隔糜烂用什么药最好_鼻中隔糜烂
当前消息!新仙剑奇侠传之挥剑问情林月如怎么获得 林月如获取方法介绍
药智网数据库 高校(药智网数据库)
沪指险守3200点 外资连续3天撤离!热门题材持续活跃
头条焦点:适合女孩子玩的单机小游戏(有哪些适合女生玩的单机小游戏?)
广州47中好不好_广州市47中高中部的重点班有哪些
记录一次服务器磁盘爆满问题
君爵商务车2023款价格及图片_君爵
环球今日讯!不愧是大哥!RTX 4090游戏本实测性能拉满
环球精选!Win11年度重磅更新Moment 3发布下载:所有Win32程序皆可沙盒运行
全球热讯:iOS 17更新内容少!原来苹果把心思放在这了
2499元起!网友对小米Civi 3定价感到意外
5月25日晚间沪深上市公司重大事项公告最新快递-环球热文
6)表连接
环球快报:铂科新材(300811)5月25日主力资金净买入56.30万元
阿里巴巴否认大裁员:今年需招15000人 每天数千岗位在纳新-天天快看
全球动态:油电同价!比亚迪宋Pro DM-i冠军版入门就71KM 13.58万起
世界资讯:14.3GB/s!PCIe 5.0 SSD第一次满血了 但是必须水冷?
环球观点:有人出18888元求票!五月天黄牛票涨回去了?
安徽男子遇AI诈骗:9秒被骗132万 世界最资讯
广东一熊孩子拿着剪刀减掉女顾客头发 家长赔偿其11500元
深圳市举行普通小汽车增量指标竞价活动 成交价创5年新低
韩国自主研发运载火箭发射升空 计划将其送入550千米高的太阳同步轨道
文心一言 VS 讯飞星火 VS chatgpt (22)-- 算法导论4.2 2题_当前简讯
11-计数器
最新消息:位运算在排序算法中的运用
浙商入川觅商机:签约项目34个 投资金额达138亿元|世界关注
惠誉发出评级警告 美债僵局如何收场|全球热议
【全球报资讯】惠誉发出评级警告 美债僵局如何收场
可追溯至40年前!日立本田合资零件厂承认长期造假
环球新资讯:必应取代百度成中国第一?百度:数据离谱 中文搜索有自信第一
每日报道:租客仅剩13元花11元买瓜探望房东:情义无价!满满正能量
爱奇艺辟谣子公司将裁员50%:不实 法务部门已介入
圣农发展:4月份销量降低是源于公司预判后期市场持续向好,增加了部分的战略库存 环球时快讯
宁波美诺华天康药业有限公司获得盐酸莫西沙星片药品注册批件
关于linux系统中umask值的说明-以及计算转换成默认权限符号的方法
焦点热议:记录--超长溢出头部省略打点,坑这么大,技巧这么多?
环球即时看!跟着hsp学springmvc--数字格式化介绍
5)基本查询语句|焦点快看
要闻速递:长城举报比亚迪排放不达标 检测机构中汽研:集团后续统一回复
《蜘蛛侠:纵横宇宙》大闹天宫海报公布:6月2日上映
美国交通部长:对特斯拉L2级智能驾驶感到担忧
5G网速起飞!小米13 Ultra双卡上网来了:下载速度猛增30% 天天最新
宝骏悦也上市 五菱大船转身:人民想要什么就造什么
世界看点:[IDEA]社区版IDEA的数据库连接插件(DB Navigator)
项目终于用上了 Spring 状态机,非常优雅!
全球热推荐:编译静态库遇到的 LNK2019 报错