Netty源码剖析——ChannelPipeline 调度 handler 的源码剖析(三十九)

ChannelPipeline 调度 handler 的源码剖析

  1. 源码剖析目的
    • 当一个请求进来的时候,ChannelPipeline 是如何调用内部的这些 handler 的
    • 首先,当一个请求进来的时候,会第一个调用 pipeline 的 相关方法,如果是入站事件,这些方法由 fire 开头表示开始管道的流动。让后面的 handler 继续处理
  2. 源码剖析
    • 说明:当浏览器输入 http://localhost:8007。可以看到会执行 handler在 Debug 时,可以将断点下在 DefaultChannelPipeline 类的
@Override
public final ChannelPipeline fireChannelActive() {AbstractChannelHandlerContext.invokeChannelActive(head);return this;
}

源码分析

DefaultChannelPipeline 是如何实现这些 fire 方法的
DefaultChannelPipeline 源码
public class DefaultChannelPipeline implements ChannelPipeline {@Overridepublic final ChannelPipeline fireChannelActive() {AbstractChannelHandlerContext.invokeChannelActive(head);return this;}@Overridepublic final ChannelPipeline fireChannelInactive() {AbstractChannelHandlerContext.invokeChannelInactive(head);return this;}@Overridepublic final ChannelPipeline fireExceptionCaught(Throwable cause) {AbstractChannelHandlerContext.invokeExceptionCaught(head, cause);return this;}@Overridepublic final ChannelPipeline fireUserEventTriggered(Object event) {AbstractChannelHandlerContext.invokeUserEventTriggered(head, event);return this;}@Overridepublic final ChannelPipeline fireChannelRead(Object msg) {AbstractChannelHandlerContext.invokeChannelRead(head, msg);return this;}@Overridepublic final ChannelPipeline fireChannelReadComplete() {AbstractChannelHandlerContext.invokeChannelReadComplete(head);return this;}@Overridepublic final ChannelPipeline fireChannelWritabilityChanged() {AbstractChannelHandlerContext.invokeChannelWritabilityChanged(head);return this;}
}
说明:
可以看出来,这些方法都是 inbound 的方法,也就是入站事件,调用静态方法传入的也是 mbound 的类型 headhandler。这些静态方法则会调用 head 的 ChannelInboundImvoker 接口的方法,再然后调用 handler 的真正方法
public class DefaultChannelPipeline implements ChannelPipeline {@Overridepublic final ChannelFuture bind(SocketAddress localAddress) {return tail.bind(localAddress);}@Overridepublic final ChannelFuture connect(SocketAddress remoteAddress) {return tail.connect(remoteAddress);}@Overridepublic final ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {return tail.connect(remoteAddress, localAddress);}@Overridepublic final ChannelFuture disconnect() {return tail.disconnect();}@Overridepublic final ChannelFuture close() {return tail.close();}@Overridepublic final ChannelFuture deregister() {return tail.deregister();}@Overridepublic final ChannelPipeline flush() {tail.flush();return this;}@Overridepublic final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {return tail.bind(localAddress, promise);}@Overridepublic final ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {return tail.connect(remoteAddress, promise);}@Overridepublic final ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {return tail.connect(remoteAddress, localAddress, promise);}@Overridepublic final ChannelFuture disconnect(ChannelPromise promise) {return tail.disconnect(promise);}
}

 

说明:

1) 这些都是出站的实现,但是调用的是 outbound 类型的 tail handler 来进行处理,因为这些都是 outbound 事件

2)出站是 tail 开始,入站从 head 开始。因为出站是从内部向外面写,从tail 开始,能够让前面的 handler 进行处理,防止 handler 被遗漏,比如编码。反之,入站当然是从 head 往内部输入,让后面的 handler 能够处理这些输入的数据。比如解码。因此虽然 head 也实现了 outbound 接口,但不是从 head 开始执行出站任务

3)关于如何调度,用一张图来表示

说明:

1) pipeline 首先会调用 Context 的静态方法 fireXXX,并传入 Context

2)然后,静态方法调用 Context 的 invoker 方法,而 invoker 方法内部会调用该 Context 所包含的Handler 的真正的 XXX 方法,调用结束后,如果还需要继续向后传递,就调用 Context 的 fireXXX2 方法,循环往复。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/586117.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

突破编程_前端_JS编程实例(分割窗体组件)

1 开发目标 分隔窗体组件旨在提供灵活的窗体分隔功能,支持横向分割与纵向分隔两种类型,并具备拖拽调整窗体比例的功能,同时提供最小比例设置,以防止窗体被过度缩小: 2 详细需求 2.1 分隔窗体类型 (1&…

数据类型和类型检测

Data Type And Type Checking 1.编程语言中的数据类型 类型和变量 一个类型是一系列值的集合,这些集合可以抽象出一个相同的特点,并且可以相互实现计算 例如: 布尔类型:true or false整形:1,2,3…浮点数类型&#xf…

JUC:double-checked locking(DCL) 懒汉单例模式

文章目录 double-checked locking(DCL) 问题解决方法 volatile作用 double-checked locking(DCL) 问题 第一个if用于后续进入的线程,不用再获取锁来判断是否已经创建了对象。第二个if,为的是第一个进入的线程创建对象,以及防止卡在第一个if之…

提升你的CSS技能:深入理解伪类选择器和伪元素选择器!

在CSS的世界里,有些选择器并不像它们的名字那样直接。今天,我们要探索的是两种特殊的选择器:伪类选择器和伪元素选择器。它们虽然名字相似,但功能和用途却大有不同。 下面就让我们一起来了解一下它们是如何在我们的页面布局中扮演…

GoogleNet神经网络介绍

一、简介 GoogleNet,也称为GoogLeNet,是谷歌工程师设计的一种深度神经网络结构,它在2014年的ImageNet图像识别挑战赛中取得了冠军。该神经网络的设计特点主要体现在其深度和宽度上,通过引入名为Inception的核心子网络结构&#x…

vue项目视频播放ckplayer使用

ckplayer 官方网址,点击访问 1,打开网页后能看到这里,我现在使用的是最新 X3版手册 2,这个ckplayer不是npm 插件,要下载安装包解压到项目里面使用 安装包网址 通过gitee下载 3,解析安装包到项目中 publ…

护眼台灯哪个牌子最好,护眼台灯五大品牌墙裂分享

近视在儿童中愈发普遍,许多家长开始认识到,除了学业成绩之外,孩子的视力健康同样重要。毕竟,学业的落后可以逐渐弥补,而一旦孩子近视,眼镜便可能成为长期伴随。因此,专业的护眼台灯对于每个家庭…

【zlm】音视频流与音频流合并的设计

目录 设想一 设想二 方案三 关键技术 测试语句 测试脚本 参考文档 设想一 //开始录制_option.mp4_save_path custom_path;_option.mp4_max_second max_second;vector<Track::Ptr> mytracks getTracks();auto src MediaSource::find( DEFAULT_VHOST, "1&quo…

今天起,ChatGPT无需注册就能用了!

就在刚刚&#xff0c;OpenAI狠狠地open了一把&#xff1a; 从今天起&#xff0c;ChatGPT打开即用&#xff0c;无需再注册帐号和登录了&#xff01; 像这样&#xff0c;直接登录网站&#xff0c;然后就可以开启对话&#xff1a; OpenAI对发布这个“超自由版ChatGPT”的解释是&am…

将 EDI 从 VAN 迁移到知行之桥:EDI 成本降低 90%

G公司帮助零售商在网上和实体店取得成功&#xff0c;是来自300家顶级制造商网络中包含狩猎&#xff0c;钓鱼&#xff0c;露营和体育用品等45,000 多种商品的批发分销商。 通过可靠的客户服务、良好的定价和超越标准大卖场产品的库存量&#xff0c;G公司的重点是为零售商、电子…

JavaScript邂逅

文章目录 Javascript内容邂逅JavaScript前端的三大核心计算机语言认识编程语言常见的编程语言编程语言的发展历史–机器语言阶段一: 机器语言 编程语言的发展历史–汇编语言阶段二:汇编语言 汇编语言的发展历史–高级语言阶段三:高级语言 机器语言和高级语言 认识JavaScriptJav…

Vmware虚拟机远程SSH连接失效解决方法及分析过程

问题描述 系统为CentOS7 64位 一向能够正常连接 在某次使用FinalShell进行远程SSH连接时 突然无法连接 对问题原因猜测及尝试 1.dns解析失效 发现显示DNS无法解析,可以得知是使用了主机名登录,而主机名无法登录. 遂查看host文件.host文件因不知名原因被清空,重新恢复后该问…