首页 > 其他分享 >netty入门-6 Handler和Pipeline

netty入门-6 Handler和Pipeline

时间:2024-07-25 20:53:50浏览次数:14  
标签:netty Pipeline ctx write Handler msg new

前言

书上讲服务器客户端创建三个要点,线程模型(Group),IO模型(NioSocketChannel),处理逻辑。
这篇的HandlerPipeline,就是我们IO操作的处理逻辑。
然后下篇说ByteBuf这个Netty自己实现的数据封装组件。

Handler和Pipeline

我们主要谈论ChannelHandlerChannelPipeline
前文也说过这俩东西,Pipeline就是多个Handler构成的。
数据经过多个Handler处理,不就是一个流水线加工的形式吗。
下面来具体说说。

首先,一个连接对应一个Channel,这是前面说到过的。每个连接经过ServerSocketChannel处理连接请求,生成一个与之对应的SocketChannel
而每个Channel同样也对应一个Pipeline。而一个Pipeline可能里面有多个Handler了。Pipeline内部的Handler是双向链表形式连接。

ChannelHandler接口有两个子接口,ChannelInboundHandler(实现类 ChannelInboundHandlerAdapter)和ChannelOutboundHandler(实现类 ChannelOutboundHandlerAdapter)。
顾名思义,Inbound自然是读数据时的处理,而Outbound是写数据时的处理。
Inbound的方法是channelRead(),对应channel读取数据时做的处理。
Outbound的方法是write(),对应向channel写数据之前做什么处理。

所以ChannelInboundHandlerAdapter内重写的channelRead()会在读取Channel数据时触发。
ChannelOutboundHandlerAdapter内重写的write()在写操作时触发。

Handler构成的双向链表就可以看做Pipeline
那么这个双向链表是什么样的呢?
先看示例代码添加的Handler

new ServerBootstrap()
    .group(new NioEventLoopGroup())
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializer<NioSocketChannel>() {
        protected void initChannel(NioSocketChannel ch) {
            ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
                    System.out.println(1);
                    ctx.fireChannelRead(msg); // 1
                }
            });
            ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
                    System.out.println(2);
                    ctx.fireChannelRead(msg); // 2
                }
            });
            ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
                    System.out.println(3);
                    ctx.channel().write(msg); // 3
                }
            });
            ch.pipeline().addLast(new ChannelOutboundHandlerAdapter(){
                @Override
                public void write(ChannelHandlerContext ctx, Object msg, 
                                  ChannelPromise promise) {
                    System.out.println(4);
                    ctx.write(msg, promise); // 4
                }
            });
            ch.pipeline().addLast(new ChannelOutboundHandlerAdapter(){
                @Override
                public void write(ChannelHandlerContext ctx, Object msg, 
                                  ChannelPromise promise) {
                    System.out.println(5);
                    ctx.write(msg, promise); // 5
                }
            });
            ch.pipeline().addLast(new ChannelOutboundHandlerAdapter(){
                @Override
                public void write(ChannelHandlerContext ctx, Object msg, 
                                  ChannelPromise promise) {
                    System.out.println(6);
                    ctx.write(msg, promise); // 6
                }
            });
        }
    })
    .bind(8080);

上述代码最后形成的双向链表是这样的。
在这里插入图片描述

这不就是按add的顺序插进链表吗。确实是,但是执行操作的顺序是有变化的。
我们的读事件,会按链表中的Inbound的顺序从前向后传递。每个Handler执行自己的逻辑然后把事件传给下一个InboundHandler。当然,不会传给OutboundHandler。按图来说就是In_1,In_2,In_3的顺序
而对于写事件在OutboundHandler中的传播顺序则与添加顺序相反,是从链表尾部最后addOutboundHandler开始向前传到第一个OutboundHandler。按图,执行顺序为,Out_6,Out_5,Out_4
inboundHandler的执行顺序与实际的添加顺序相同,而outboundHandler则相反。

结语

本文仅涉及到Handler处理的触发顺序。对于我们使用时一般在Handler里做什么没有介绍。一般来说就是做数据的编码解码,或者打印一些信息。

总结一下,每个Channel有自己的Pipeline,内部的Handler有我们进行配置。
其中读会走InboundHandler处理。写会走OutBoundHandler处理。
还有就是执行顺序,InboundHandler的执行顺序与添加顺序相同。OutBoundHandler则是相反。

下篇就是数据载体ByteBuf了。
然后基本组件就说完了。Netty的基本使用也就是这些组件的使用。
剩下的就是一些组件深层次的原理与现象了(比如主从Reactor模型,组件的源码实现),这部分可能不影响使用,但对于理解Netty很有帮助。

我觉得仅仅了解这些东西的基本使用,我们还是很难用它去做一个什么聊天室,RPC之类的东西。
所以还是需要学习别人怎么做的,做这个的框架,要有什么样的功能怎么实现,会出现什么问题怎么解决。

感谢阅读,欢迎批评指正。

标签:netty,Pipeline,ctx,write,Handler,msg,new
From: https://blog.csdn.net/qq_42939279/article/details/140698668

相关文章

  • 使用Spring Boot和Netty打造高性能聊天服务(一):基础入门
    使用SpringBoot和Netty打造高性能聊天服务(一):基础入门在现代互联网应用中,实时聊天功能已经成为了许多应用的标配。无论是社交应用、在线客服系统,还是游戏中的实时交流,聊天功能都扮演着重要角色。今天,我们将使用SpringBoot和Netty来构建一个高性能的聊天服务。本文是系列文章的第......
  • netty应用-手写RPC
    文章目录手写RPC之案例定位与通信过程介绍RPC框架案例定位服务端与客户端架构通信过程1.服务注册与发现2.请求序列化与传输3.请求处理与响应4.响应反序列化与结果处理实现细节1.服务端2.客户端技术选型关键挑战总结手写RPC之请求响......
  • pipeline语法讲解
     必要的Groovy知识 支持命名参数defcreateName(StringgivenName,StringfamilyName){returngivenName+""+familyName}//调用时可以这样createNamefamilyName="Lee",givenName="Bruce"支持默认参数,比如:defsayHello(Stringname="h......
  • netty入门-4 Channel与ChannelFuture
    Channel基本类似于NIO中的Channel概念。作为读写数据的通道。常见方法close()可以用来关闭channelcloseFuture()用来处理channel的关闭sync方法作用是同步等待channel关闭而addListener方法是异步等待channel关闭pipeline()方法添加处理器write()方法......
  • 流式查询2、mybatis的ResultHandler 每次查询返回定义的500条
    流式查询2、mybatis通过用ResultHandler流式查询,每次查询返回定义的500条,再去批量处理(可异步并发):packagecom.aswatson.cdc.redis.schedule;importcom.aswatson.cdc.redis.common.lock.DistLock;importcom.aswatson.cdc.redis.common.lock.DistLockRegistry;importcom.as......
  • Python爬虫(5-10)-编解码、ajax的get请求、ajax的post请求、URLError/HTTPError、微博
    五、编解码(Unicode编码)(1)GET请求所提方法都在urllib.parse.路径下get请求的quote()方法(适用于只提交一两个参数值)url='http://www.baidu.com/baidu?ie=utf-8&wd='#对汉字进行unicode编码name=urllib.parse.quote('白敬亭')url+=nameget请求的urlencode()方法(适用于......
  • Transformers Pipeline + Mistral-7B-Instruct-v0.x修改Chat Template
    在使用https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.3提供的Generatewithtransformers代码进行测试时,产生以下报错:fromtransformersimportpipelinemessages=[{"role":"system","content":"Youareapiratechatbotwhoalw......
  • 数据结构与算法 —— Transformers之Pipeline
    Transformers之Pipeline是HuggingFaceTransformers库中提供的一种使用预训练模型进行推理的极简方式。这些Pipeline对象从库中抽象出大部分复杂代码,为多项任务(如命名实体识别、情感分析、特征提取和问答等)提供了简单的API。以下是对Transformers之Pipeline的详细介绍:一、......
  • 【人工智能】Transformers之Pipeline(一):音频分类(audio-classification)
    ​​​​​​​目录一、引言 二、音频分类(audio-classification)2.1概述2.2技术原理2.2.1 Wav2vec2.0模型 2.2.1HuBERT模型2.3pipeline参数2.3.1pipeline对象实例化参数2.3.2pipeline对象使用参数 2.4 pipeline实战2.4.1指令识别(默认模型) 2.4.2 情......
  • 【人工智能】Transformers之Pipeline(概述):30w+大模型极简应用
    ​​​​​​​目录一、引言 二、pipeline库2.1概述2.2使用task实例化pipeline对象2.2.1基于task实例化“自动语音识别”2.2.2task列表2.2.3 task默认模型2.3 使用model实例化pipeline对象2.3.1基于model实例化“自动语音识别” 2.3.2查看model与task的......