Netty事件监听和处理(下)
上一篇 介绍了事件监听、责任链模型、socket接口和IO模型、线程模型等基本概念,以及Netty的整体结构,这篇就来说下Netty三大核心模块之一:事件监听和处理。
前面提到,Netty是一个NIO框架,它将IO通道的建立、可读、可写等状态变化,抽象成事件,以责任链的方式进行传递,可以在处理链上插入自定义的Handler,对感兴趣的事件进行监听和处理。
通过介绍,你会了解到:
- 事件监听和处理模型
- 事件监听:EventLoop
- 事件处理:ChannelPipeline和ChannelHandler
- 使用Netty实现Websocket协议
文章末尾有福利 ~
事件监听和处理模型
进行网络编程时,一般的编写过程是这样的:
- 创建服务端Socket,监听某个端口;
- 当有客户端连接时,会创建一个新的客户端Socket,监听数据的可读、可写状态,每一个连接请求都会创建一个客户端Socket;
- 读取和写入数据都会调用Socket提供的接口,接口列表在上一篇提到过;
传统的模型,每个客户端Socket会创建一个单独的线程监听socket事件,一方面系统可创建的线程数有限,限制了并发数,一方面线程过多,线程切换频繁,导致性能严重下降。
随着操作系统IO模型的发展,可以采用多路复用IO,一个线程监听多个Socket,另外,服务端处理客户端连接,与客户端Socket的监听,可以在不同的线程进行处理。
Netty就是采用多路复用IO进行事件监听,另外,使用不同的线程分别处理客户端的连接、数据读写。
整个处理结构如下图,简单说明下:
- Boss EventLoopGroup主要处理客户端的connect事件,包含多个EventLoop,每个EventLoop一个线程;
- Worker EventLoopGroup主要处理客户端Socket的数据read、write事件,包含多个EventLoop,每个EventLoop一个线程;
- 无论是Boos还是Worker,事件的处理都是通过Channel Pipleline组织的,它是责任链模式的实现,包含一个或多个Handler;
- 侦听一个端口,只会绑定到Boss EventLoopGroup中的一个Eventloop;
- Worker EventLoopGroup中的一个Eventloop,可以监听多个客户端Socket;

EventLoop
一个EventLoop其实和一个特定的线程绑定, 并且在其生命周期内, 绑定的线程都不会再改。
EventLoop肩负着两种任务:
- 第一个是作为 IO 线程, 执行与 Channel 相关的 IO 操作, 包括 调用select等待就绪的IO事件、读写数据与数据的处理等;
- 第二个任务是作为任务队列, 执行 taskQueue 中的任务, 例如用户调用eventLoop.schedule提交的定时任务也是这个线程执行的;
第一个任务比较好理解,主要解释下第二个:从socket数据到数据处理,再到写入响应数据,Netty都在一个线程中处理,主要是为了线程安全考虑,减少竞争和线程切换,通过任务队列的方式,可以在用户线程提交处理逻辑,在Eventloop中执行。
整个EventLoop干的事情就是select -> processIO -> runAllTask,processIO处理IO事件相关的逻辑,runAllTask处理任务队列中的任务,如果执行的任务过多,会影响IO事件的处理,所以会限制任务处理的时间,整个处理过程如下图:

EventLoop的run代码如下:
1 |
protected void run() {
|
ChannelPipeline和ChannelHandler
ChannelPipeline是一个接口,其有一个默认的实现类DefaultChannelPipeline,内部有两个属性:head和tail,
这两者都实现了ChannelHandler接口,对应处理链的头和尾。
1 |
protected DefaultChannelPipeline(Channel channel) {
|
每个Channel创建时,会创建一个ChannelPipeline对象,来处理channel的各种事件,可以在运行时动态进行动态修改其中的 ChannelHandler。
ChannelHandler承载业务处理逻辑的地方,我们接触最多的类,可以自定义Handler,加入处理链中,实现自定义逻辑。
ChannelHandler 可分为两大类:ChannelInboundHandler 和 ChannelOutboundHandle,这两接口分别对应入站和出站消息的处理,对应数据读取和数据写入。它提供了接口方法供我们实现,处理各种事件。
1 |
public interface ChannelInboundHandler extends ChannelHandler {
|
自定义Handler时,一般继承ChannelInboundHandlerAdapter或 ChannelOutboundHandlerAdapter。
需要注意的是,不建议在 ChannelHandler 中直接实现耗时或阻塞的操作,因为这可能会阻塞 Netty 工作线程,导致 Netty 无法及时响应 IO 处理。

使用Netty实现Websocket协议
Websocket协议
不是本篇的重点,简单说明下:
- 是一种长连接协议,大部分浏览器都支持,通过websocket,服务端可以主动发消息给客户端;
- Websocket协议,在握手阶段使用HTTP协议,握手完成之后,走Websocket自己的协议;
- Websocket是一种二进制协议;
初始化
Netty提供了ChannelInitializer类方便我们初始化,创建WebSocketServerInitializer类,继承ChannelInitializer类,用于添加ChannelHandler:
1 |
public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel> {
@Resource
|
分析下这几个Handler,都是Netty默认提供的:
- HttpServerCodec:用于解析Http请求,主要在握手阶段进行处理;
- HttpObjectAggregator:用于合并Http请求头和请求体,主要在握手阶段进行处理;
- WebSocketServerProtocolHandler:处理Websocket协议;
- CustomTextFrameHandler:自定义的Handler,用于添加自己的业务逻辑。
是不是很方便,经过WebSocketServerProtocolHandler处理后,读取出来的就是文本数据了,不用自己处理数据合包、拆包问题。
CustomTextFrameHandler
自定义的Handler,进行业务处理:
1 |
public class CustomTextFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
|
福利说明
最后,说下福利:小爱音箱F码。
准备了2份,主要为了感谢「微信公众号」和「掘金社区」的朋友,每一份包括1个小爱音箱F码和1个小爱音箱 mini F码。
小米手机F码源自于英文单词”Friend”,是小米公司提供给小米核心用户及为小米做出贡献的网友的优先购买权,如果您有小米F码的话无需等待即可直接利用小米F码购买相关产品!
简单来说,F码就是不用抢了,可以直接购买 ~
抽奖截止时间
4月9号中午12点
抽奖规则
掘金社区
需要关注我的掘金账号才有效,个人主页;
使用微信抽奖助手随机抽取for掘金社区;
微信公众号
需要关注我的微信公众号才有效;
使用微信抽奖助手随机抽取for微信公众号;
Netty事件监听和处理(下)的更多相关文章
- Netty事件监听和处理(上)
陪产假结束了,今天又开始正常上班了,正好赶上米粉节活动,又要忙上一阵了,米粉节活动时间为4.03 - 4.10,有不少优惠,感兴趣的可以关注mi.com或小米商城app. 今天给大家送了福利:小爱音箱 ...
- js中如何在不影响既有事件监听的前提下新增监听器
一. 需求澄清 比如某个按钮已经绑定了2-3个对Window对象的load事件的监听,现在需要添加一个新的对click事件的监听器,但在一定条件下才会同时触发原有的2-3个load监听器,否则只触发新 ...
- 9、JcomboBox下拉框事件监听
9.JcomboBox下拉框事件监听 JComboBox()的事件监听类ItemListener.其范例代码如下: import java.awt.*; import java.awt.event.* ...
- Zookeeper Curator 事件监听 - 秒懂
目录 写在前面 1.1. Curator 事件监听 1.1.1. Watcher 标准的事件处理器 1.1.2. NodeCache 节点缓存的监听 1.1.3. PathChildrenCache ...
- Node.js 教程 05 - EventEmitter(事件监听/发射器 )
目录: 前言 Node.js事件驱动介绍 Node.js事件 注册并发射自定义Node.js事件 EventEmitter介绍 EventEmitter常用的API error事件 继承EventEm ...
- .NET事件监听机制的局限与扩展
.NET中把“事件”看作一个基本的编程概念,并提供了非常优美的语法支持,对比如下C#和Java代码可以看出两种语言设计思想之间的差异. // C#someButton.Click += OnSomeB ...
- 让 select 的 option 标签支持事件监听(如复制操作)
这标题,让option支持事件监听,应该不难的呀,有什么好讲的? 其实还是有的,默认在浏览器代码是无法直接对option标签进行操作的,不仅包括JS事件监听,还是CSS样式设置 查了一些资料,姑且认为 ...
- [JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播
-->事件冒泡和捕获-->事件监听-->阻止事件传播 一.事件冒泡和捕获 1.概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的oncl ...
- [No00006A]Js的addEventListener()及attachEvent()区别分析【js中的事件监听】
1.添加时间监听: Chrom中: addEventListener的使用方式: target.addEventListener(type, listener, useCapture); target ...
随机推荐
- 21.jQuery
简介 jQuery是一个快速.简洁的JavaScript框架,jQuery设计的宗旨是"write Less,Do More",即倡导写更少的代码,做更多的事情.它封装JavaSc ...
- 【翻译】《向“弹跳球”演示程序添加新功能》 in MDN
文章地址: https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/%E5%90%91%E2%80%9C%E5%BC%B9% ...
- ios开发数据库版本迁移手动更新迭代和自动更新迭代艺术(二)
由于大家都热衷于对ios开发数据库版本迁移手动更新迭代和自动更新迭代艺术(一)的浏览下面我分享下我的源文件git仓库: 用法(这边我是对缓存的一些操作不需要可以省去):https://github.c ...
- 进程优化工具Process Lasso Pro 8.4官方版+激活破解方法
Process Lasso是一款来自美国的系统进程优化工具,基于特殊算法动态调整进程的优先级别,通过合理的设置进程优先级来实现降低系统负担的功能.可有效避免蓝 屏.假死.进程停止响应.进程占用 CPU ...
- 利用XAMPP本地搭建WordPress博客
现在越来越多的人利用WordPress搭建了自己的博客网站,我也是一样,但是还有一些人不知道怎么搭建WordPress网站的方法,因为怕弄 不好,所以也就没有花钱去做,所以这里我就讲讲怎么样利用XAM ...
- Linux压缩命令总结
2018-02-28 10:43:18 linux压缩和解压缩命令大全 tar命令:tar本身仅是一个打包的命令,不具有压缩的功能.打包后源文件仍然存在,具有将多个文件归档成一个文件的功能[root ...
- 20165226 学习基础和C语言基础调查
心得体会 驱动迭代 学习是一个老师与学生互动的过程,二者关系又恰如健身教练与学员,在进行基础知识的培训后还需借助工具加强相关方面的训练.学习提升的过程离不开学生在实践中发现问题并在老师的帮助下解决问题 ...
- 读取pdf内容分页和全部
//读取pdf 全部内容public static String topdffile(String pdffile){ StringBuffer result = new StringBuffer() ...
- 基于JavaMail向邮箱发送邮件
参考:http://blog.csdn.net/ghsau/article/details/17839983 http://blog.csdn.net/never_cxb/article/detail ...
- Maven-07: 插件的自定义绑定
除了内置绑定以外,用户还能够自己选择将某个插件目标绑定到生命周期的某个阶段上,这种自定义绑定方式能让Maven项目在构建过程中执行更多更富特色的任务. 一个常见的例子是创建项目的源码jar包.内置的插 ...