io.netty学习(四)ChannelHandler

这篇具有很好参考价值的文章主要介绍了io.netty学习(四)ChannelHandler。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

正文

ChannelHandler

ChannelInboundHandler

ChannelOutboundHandler

ChannelDuplexHandler

总结


前言

先简略了解一下ChannelPipelineChannelHandler的概念。

想象一个流水线车间。当组件从流水线头部进入,穿越流水线,流水线上的工人按顺序对组件进行加工,到达流水线尾部时商品组装完成。可以将ChannelPipeline当做流水线,ChannelHandler当做流水线工人。源头的组件当做event,如read,write等等。

本篇文章我们先来讲讲ChannelHandler的相关知识,下面进入正文吧。

io.netty学习使用汇总 

正文

ChannelHandler

  • ChannelHandler并不处理事件,而由其子类代为处理:ChannelInboundHandler拦截和处理入站事件,ChannelOutboundHandler拦截和处理出站事件。

  • ChannelHandlerChannelHandlerContext通过组合或继承的方式关联到一起成对使用。事件通过ChannelHandlerContext主动调用如fireXXX()write(msg)等方法,将事件传播到下一个处理器。

注意:入站事件在ChannelPipeline双向链表中由头到尾正向传播,出站事件则方向相反。

ChannaleHandler 作为最顶层的接口,并不处理入站和出站事件,所以接口中只包含最基本的方法:

 // Handler本身被添加到ChannelPipeline时调用
 void handlerAdded(ChannelHandlerContext var1) throws Exception;
  // Handler本身被从ChannelPipeline中删除时调用
 void handlerRemoved(ChannelHandlerContext var1) throws Exception;
 
 // 发生异常时调用
 @Deprecated
 void exceptionCaught(ChannelHandlerContext var1, Throwable var2) throws Exception;

Sharable注解:

当客户端连接到服务器时,Netty新建一个ChannelPipeline处理其中的事件,而一个ChannelPipeline中含有若干ChannelHandler。如果每个客户端连接都新建一个ChannelHandler实例,当有大量客户端时,服务器将保存大量的ChannelHandler实例。为此,Netty提供了Sharable注解,如果一个ChannelHandler状态无关,那么可将其标注为Sharable,如此,服务器只需保存一个实例就能处理所有客户端的事件。

 @Inherited
 @Documented
 @Target({ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Sharable {
 }

作为ChannelHandler的默认实现,ChannelHandlerAdapter有个重要的方法isSharable(),代码如下:

 public boolean isSharable() {
     Class<?> clazz = this.getClass();
     // 每个线程一个缓存
     Map<Class<?>, Boolean> cache = InternalThreadLocalMap.get().handlerSharableCache();
     Boolean sharable = (Boolean)cache.get(clazz);
     if (sharable == null) {
         // Handler是否存在Sharable注解
         sharable = clazz.isAnnotationPresent(Sharable.class);
         cache.put(clazz, sharable);
     }
 
     return sharable;
 }

这里引入了优化的线程局部变量InternalThreadLocalMap,即每个线程都有一份ChannelHandler是否Sharable的缓存。这样可以减少线程间的竞争,提升性能。

ChannelInboundHandler

ChannelInboundHandler处理入站数据以及各种状态变化,当Channel状态发生改变会调用ChannelInboundHandler中的一些生命周期方法。这些方法与Channel的生命密切相关。

入站数据,就是进入socket的数据。下面展示一些该接口的生命周期API:

io.netty学习(四)ChannelHandler

ChannelInboundHandlerAdapter作为ChannelInboundHandler的实现,默认将入站事件自动传播到下一个入站处理器。其中的代码高度一致,如下:

 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
     ctx.fireChannelRead(msg);
 }

ChannelOutboundHandler

出站操作和数据将由 ChannelOutboundHandler 处理。它的方法将被 Channel、 ChannelPipeline 以及 ChannelHandlerContext 调用。ChannelOutboundHandler 的一个强大的功能是可以按需推迟操作或者事件,这使得可以通过一些复杂的方法来处理请求。

例如, 如果到远程节点的写入被暂停了, 那么你可以推迟冲刷操作并在稍后继续。

io.netty学习(四)ChannelHandler

同理,ChannelOutboundHandlerAdapter作为ChannelOutboundHandler的事件,默认将出站事件传播到下一个出站处理器:

 @Override
 public void read(ChannelHandlerContext ctx) throws Exception {
     ctx.read();
 }

ChannelDuplexHandler

ChannelDuplexHandler则同时实现了ChannelInboundHandlerChannelOutboundHandler接口。如果一个所需的ChannelHandler既要处理入站事件又要处理出站事件,推荐继承此类。

总结

以上就是关于ChannelHandler的分析,相信你对ChannelHandler也有一定的了解,下期我们再来分析ChannelPipeline的源码。文章来源地址https://www.toymoban.com/news/detail-501121.html

到了这里,关于io.netty学习(四)ChannelHandler的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设置word目录从正文开始记录页码,并解决word目录正常,但正文页脚处只显示第一页的页码

    问题详情1:如何设置目录从正文开始记录页码 问题详情2:word目录处的页码正常,但正文只有第一页的页脚处显示页码 在设置目录从正文开始记录页码时需在目录后插入分节符(相同的节可以把当前页的页脚链接到上一页,但是不同的节就不行,因此可以利用分节来从 正文

    2024年03月10日
    浏览(95)
  • io.netty学习(二)Netty 架构设计

    目录 前言 Selector 模型 SelectableChannel Channel 注册到 Selector SelectionKey 遍历 SelectionKey 事件驱动 Channel 回调 Future 事件及处理器 责任链模式 责任链模式的优缺点 ChannelPipeline 将事件传递给下一个处理器 总结 上一篇文章,我们对  Netty 做了一个基本的概述,知道什么是 Netty 以及

    2024年02月10日
    浏览(35)
  • io.netty学习(三)Channel 概述

    目录 前言 正文 Channel概述 Channel 特点 Channel 接口方法 ChannelOutboundInvoker AttributeMap 总结 前两篇文章我们已经对 Netty 进行了简单的了解和架构设计原理的剖析。 本篇文章我们就来开始对 Netty 源码的分析,首先我们来讲解 Netty 中 Channel 相关的功能和接口。 io.netty学习使用汇总

    2024年02月09日
    浏览(30)
  • 文件IO,目录IO的学习

    用法:#include“head.h”    -     在当前目录下寻找头文件 主函数的传参中,argc是传参的个数  ,const char *argv[]是一个指针数组,存放的指针类型数据 argv【n】,n=1/2/3 分别代表三个指针参数 标准示例:     off_t lseek(int fd, off_t offset, int whence);        功能:            

    2024年02月20日
    浏览(24)
  • 《Git入门实践教程》前言+目录

    版本控制系统(VCS)在项目开发中异常重要,但和在校大学生的交流中知道,这个重要方向并未受到重视。具备这一技能,既是项目开发能力的体现,也可为各种面试加码。在学习体验后知道,Git多样化平台、多种操作方式、丰富的资源为业内人士提供了方便的同时,也造成

    2024年02月10日
    浏览(50)
  • 目录IO 2月19日学习笔记

     1. lseek        off_t lseek(int fd, off_t offset, int whence);        功能:             重新设定文件描述符的偏移量        参数:             fd:文件描述符             offset:偏移量             whence:                 SEEK_SET    文件开头                 SEEK_CUR    文件当前

    2024年02月20日
    浏览(27)
  • 嵌入式Linux学习DAY21--目录io

    对主函数传参: ./a.out +参数1(指针数组),参数2....... 在代码中,要写成 int main(参数数量,const char *指针数组) lseek(a,b,c):                功能:重新设定文件描述符的偏移量                参数:a:文件描述符                           b:偏移量         

    2024年02月20日
    浏览(34)
  • gateway报 netty堆外内存溢出问题解决io.netty.util.internal.OutOfDirectMemoryError

    昨天线上网关突然无法访问。打开日志看到错误信息“io.netty.util.internal.OutOfDirectMemoryError” 堆外内存溢出。。这也没碰到过啊,看来今天准点下班的愿望又落空了。老规矩面向百度编程。先看看网上有没有其他兄弟碰到这个问题。一顿搜索之后发现,很多博客都是一知半解并

    2024年02月10日
    浏览(46)
  • Spingboot 整合netty-socket.io

    依赖 注意版本号,不然client版本不对的话也是连不上的 https://github.com/mrniko/netty-socketio ​ `` 结构 3 配置 4 .ClientCache `` 5 . 连接处理类 6.工具处理类 7.NettySocketRunnable yaml 配置 8:nginx 配置 协议升级 wss(443) 或ws(80) 1: 注意server的版本和client版本是对应上的 2: 上线后注意线上是否

    2024年02月15日
    浏览(30)
  • 【redis问题】Caused by: io.netty.channel

    在使用 RedisTemplate 连接 Redis 进行操作的时候,发生了如下报错: 测试代码为: 配置文件:

    2024年02月11日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包