Netty中inboundHandler与outboundHandler的执行顺序

第二章Netty Netty OutboundHandler 全解析 摘要: Netty的OutboundHandler是处理出站事件的核心组件,负责将本地数据写入网络通道,与InboundHandler形成对称事件处理体系。其事件传递方向与入站相反(从Tail到Head),需注意执行顺序问题。核心方法包括connect、bind、write、flush等,支持事件传递或自定义拦截。典型应用如编码器(如StringEncoder),实现业务对象到字节流的转换。开发时需注意:1)编码器应靠近Pipeline尾部;2)无状态Handler可标记@Sharable复用;3)避免吞没 阅读详情

一个疑问

首先一切的一切,是从一次意外开始。

在写一个netty的server的时候,这里有四个handler,inboundHandler实现的类EchoInHandler1与EchoInHandler2,outboundHandler实现的类EchoOutHandler1与EchoOutHandler2;

在添加到pipeline的时候,如果这些handler的存放到pipeline的位置为EchoOutHandler1-EchoOutHandler2-EchoInHandler1-EchoInHandler2,那么一切就正常了。

开始监听,端口为:/127.0.0.1:20000
in1
in2
接收客户端数据:QUERY TIME ORDER
server向client发送数据
out2
out1
Complete1

但是如果存放的顺序是EchoInHandler1-EchoInHandler2-EchoOutHandler1-EchoOutHandler2,那么会出现在出站的时候,EchoOutHandler1与EchoOutHandler2却没有执行。

开始监听,端口为:/127.0.0.1:20000
in1
in2
接收客户端数据:QUERY TIME ORDER
server向client发送数据
Complete1

这是为什么呢?
PS:如果想知道答案可以直接看最后一节

public void start() throws Exception {
    EventLoopGroup eventLoopGroup = null;
    try {
        //server端引导类
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        //连接池处理数据
        eventLoopGroup = new NioEventLoopGroup();
        serverBootstrap.group(eventLoopGroup)
            .channel(NioServerSocketChannel.class)
            //指定通道类型为NioServerSocketChannel,一种异步模式,OIO阻塞模式为OioServerSocketChannel
            .localAddress("localhost",port)
            //设置InetSocketAddress让服务器监听某个端口已等待客户端连接。
            .childHandler(new ChannelInitializer<Channel>() {
                //设置childHandler执行所有的连接请求
                @Override
                protected void initChannel(Channel ch) throws Exception {
           // 注册两个InboundHandler,执行顺序为注册顺序,所以应该是InboundHandler1 InboundHandler2
           // 注册两个OutboundHandler,执行顺序为注册顺序的逆序,所以应该是OutboundHandler2 OutboundHandler1
                    ch.pipeline().addLast(new EchoInHandler1());
                    ch.pipeline().addLast(new EchoInHandler2());
                    ch.pipeline().addLast(new EchoOutHandler1());
                    ch.pipeline().addLast(new EchoOutHandler2());
                }
            });
        // 最后绑定服务器等待直到绑定完成,调用sync()方法会阻塞直到服务器完成绑定,
        // 然后服务器等待通道关闭,因为使用sync(),所以关闭操作也会被阻塞。
        ChannelFuture channelFuture = serverBootstrap.bind().sync();
        System.out.println("开始监听,端口为:" + channelFuture.channel().localAddress());
        channelFuture.channel().closeFuture().sync();
    } finally {
        eventLoopGroup.shutdownGracefully().sync();
    }
}

EchoInHandler1

package com.aguicode.practice.netty.mutilhandler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * @author aguicode
 * @since 2020-3-8
 */
public class EchoInHandler1 extends ChannelInboundHandlerAdapter {

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		System.out.println("in1");
		// 通知执行下一个InboundHandler
		ctx.fireChannelRead(msg);
		//ctx.writeAndFlush(msg);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		System.out.println("Complete1");
		//ctx.flush();//刷新后才将数据发出到SocketChannel
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		ctx.close();
	}
}

EchoInHandler2

package com.aguicode.practice.netty.mutilhandler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.Date;

/**
 * @author aguicode
 * @since 2020-3-8
 */
public class EchoInHandler2 extends ChannelInboundHandlerAdapter {


	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		System.out.println("in2");
		ByteBuf buf = (ByteBuf) msg;
		byte[] req = new byte[buf.readableBytes()];
		buf.readBytes(req);
		String body = new String(req, "UTF-8");
		System.out.println("接收客户端数据:" + body);
		//向客户端写数据
		System.out.println("server向client发送数据");
		String currentTime = new Date(System.currentTimeMillis()).toString();
		ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
		//ctx.write(resp);
		ctx.writeAndFlush(resp);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		System.out.println("Complete2");
		//ctx.flush();//刷新后才将数据发出到SocketChannel
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		ctx.close();
	}

}

EchoOutHandler1

package com.aguicode.practice.netty.mutilhandler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;

import java.util.Date;

/**
 * @author aguicode
 * @since 2020-3-8
 */
public class EchoOutHandler1 extends ChannelOutboundHandlerAdapter {

	@Override
	// 向client发送消息
	public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
		System.out.println("out1");
		/*System.out.println(msg);*/

		String response = "\nI am ok!\n";
		ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
		encoded.writeBytes(response.getBytes());

		String currentTime = new Date(System.currentTimeMillis()).toString();
		ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
		ctx.write(resp);
		ctx.writeAndFlush(encoded);
		ctx.flush();
	}
}

EchoOutHandler2

package com.aguicode.practice.netty.mutilhandler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;

/**
 * @author aguicode
 * @since 2020-3-8
 */
public class EchoOutHandler2 extends ChannelOutboundHandlerAdapter {

	@Override
	public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
		System.out.println("out2");
		// 执行下一个OutboundHandler
            /*System.out.println("at first..msg = "+msg);
            msg = "hi newed in out2";*/
		// 通知执行下一个OutboundHandler
		super.write(ctx, msg, promise);
		super.flush(ctx);
	}
}

几个重要的概念

工作原理

channelHandler双向链表

netty中有以下几个重要的概念,首先是server与client,它们中有channel、channelPipeline、channelHandler、channelHandlerContext、ServerBootStrap、bootStrap、channelFuture、selector、Eventloop;

关于Netty的组件中的介绍会安排到另外一篇详细解答,这里只是分析in与out boundHandler执行顺序

Netty负责人演讲用的PPT

原理解析

channelHandler 中定义outboundhandler和inboundhandler,表示一个请求进来时通过入站inboundhandler,而内部进行一些业务的逻辑处理之后出站使用outboundhandler,

这里handler是定义在channelPipeline里边的,handler之间是一种双向链表的关系,inBound事件从head节点传播到tail节点,outBound事件从tail节点传播到head节点。

/**
 *                                                 I/O Request
 *                                            via {@link Channel} or
 *                                        {@link ChannelHandlerContext}
 *                                                      |
 *  +---------------------------------------------------+---------------+
 *  |                           ChannelPipeline         |               |
 *  |                                                  \|/              |
 *  |    +---------------------+            +-----------+----------+    |
 *  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  |               |
 *  |               |                                  \|/              |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  .               |
 *  |               .                                   .               |
 *  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
 *  |        [ method call]                       [method call]         |
 *  |               .                                   .               |
 *  |               .                                  \|/              |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  |               |
 *  |               |                                  \|/              |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  |               |
 *  +---------------+-----------------------------------+---------------+
 *                  |                                  \|/
 *  +---------------+-----------------------------------+---------------+
 *  |               |                                   |               |
 *  |       [ Socket.read() ]                    [ Socket.write() ]     |
 *  |                                                                   |
 *  |  Netty Internal I/O Threads (Transport Implementation)            |
 *  +-------------------------------------------------------------------+
*/

例如在建立三次握手之后,开始读数据,从head节点发起,准确来说是head的unsafe方法发起,inbound寻找下一个inbound时,调用invokeChannelActive(next),一个个递归调用,直到最后一个inBound节点—即tail节点,并且tail节点作为尾节点,会终止inbound事件的传播,读事件就结束了,

这个时候,经过一段业务逻辑的处理,就需要处理outbound事件,转而反向传播,outbound则调用的是writeAndFlush(),直到head节点,数据最终会落在head节点的unsafe.write方法。


我是分割线


执行顺序的分析

那么原理都懂了,这里就重点分析一下inboundHandler与outboundHandler添加顺序不同,带来执行顺序的问题

  1. inbound事件在pipeline中传输方向是head->tail,即从头到尾,而且会忽略outbound事件
invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);

重要的是find方法

 private AbstractChannelHandlerContext findContextInbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.next;
        } while ((ctx.executionMask & mask) == 0);
        return ctx;
    }

或者类似这样子:
忽略非inbound

  1. outbound事件在pipeline传输方向正好相反,会从tail->head,即从尾到头,同时也会忽略inbound事件
 final AbstractChannelHandlerContext next = findContextOutbound(flush ?
                (MASK_WRITE | MASK_FLUSH) : MASK_WRITE);

重要的是find方法

 private AbstractChannelHandlerContext findContextOutbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while ((ctx.executionMask & mask) == 0);
        return ctx;
    }

或者类似这样子:
忽略非outbound

但是 需要关注的是:AbstractChannelHandlerContext ctx = this;

其实AbstractChannelHandlerContext是上下文都共享的,所以,

如果是EchoInHandler1-EchoInHandler2-EchoOutHandler1-EchoOutHandler2,那么一开始入站执行了EchoInHandler1-EchoInHandler2,因为do-while循环跳出,ctx留在了EchoInHandler2的位置,在出站的时候,在EchoInHandler2的位置反向遍历,只会遍历EchoInHandler2-EchoInHandler1,那么自然就不会去读取-EchoOutHandler1-EchoOutHandler2了。

相反,如果是EchoOutHandler1-EchoOutHandler2-EchoInHandler1-EchoInHandler2的顺序,一开始入站ctx到了EchoInHandler2的位置,反向遍历就会经过EchoInHandler2-EchoInHandler1-EchoOutHandler2-EchoOutHandler1

浙政钉H5应用上架实战:从环境配置到发布避坑指南 本文详细解析浙政钉H5应用上架全流程,从环境配置到发布避坑指南。重点介绍Vue 2.6 + Node 14.21.3的稳定开发环境搭建、项目结构规范及常见报错解决方案,帮助开发者高效完成浙政钉H5应用上架流程。 阅读详情

相关推荐

离散数学期末复习笔记【精华版】

文章目录前言一、????理逻辑1. 命题逻辑2. 等值演算3. 主合取范式、主析取范式4. 【题】推理证明5. 辖域、自由变元、约束变元二、????合1. 环和、环积,幂集,笛卡尔乘积三、 ????????关系1. 自反、对称、传递2&3. 合成运算,逆关系、闭包4. 哈斯图、上下界、偏序5. 等价关系、划分四、????1. 幺元(么元、单位元)、零元、逆元,半群、群、阿尔贝群、独异点、循环独异点2. 【题】由表判断3. 【题】证明五、????论1. 简单图、平凡图、多重图、子图、补图、出度、入度、

林大夕可的博客 17万+

Netty的InboundHandler 和OutboundHandler

本文说明Netty的InboundHandler 和OutboundHandler的区别,并通过示例演示客户端数据在handler的数据流向。

littleschemer的博客 1824

Sigmastar平台WDR调试实战:从参数解析到鬼影消除的完整指南

本文提供了Sigmastar平台宽动态(WDR)技术的实战调试指南。针对逆光、运动场景下的核心痛点,系统性地解析了从多曝光采集、HDR融合到色调映射的完整管线,并重点阐述了如何通过调整曝光比、运动阈值与调整曲线等关键参数,有效消除运动鬼影、平衡暗部噪声与细节,最终实现清晰稳定的图像效果。

Jerry的专栏 926

Netty: ChannelInboundHandler和ChannelOutboundHandler的使用

一、需要注意的地方: 入站的消息会流经所有的添加的ChannelInboundHandler,出站的消息不一定会流经所有的ChannelOutboundHandler,通过在某个ChannelInboundHandler的ChannelHandlerContext的writeAndFlush方法写出的数据,并不会流经其后的ChannelOuntboundHandler,但如果是通过ctx.channel().writeAndFlush方法写出数据,则会流经所有的ChannelOutboundHandler.

amadeus_liu2的博客 2207

5-->详解《switch 数据接收驱动框架、mtk7621集成交换芯片mt7530》之一

SWITCH 交换芯片驱动配置: 一、 配置 MDIO 总线 二、配置 MAC 接口 三、基于 MAC 的 DMA 配置 四、设备驱动结构体 五、数据收发包

weixin_38387929的博客 1万+

数字逻辑EduCoder课设项目 厨房计时器系统设计 Logisim实现

数字逻辑EduCoder课设项目 厨房计时器系统设计 Logisim实现

weixin_51693702的博客 1万+

Netty4.0学习笔记系列之二:Handler的执行顺序

Handler在netty中,无疑占据着非常重要的地位。Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码、拦截指定的报文、统一对日志错误进行处理、统一对请求进行计数、控制Handler执行与否。一句话,没有它做不到的只有你想不到的。 Netty中的所有handler都实现自ChannelHandler接口。按照输出输出来分,分为ChannelI

BruceOuyang 的专栏 1339

阿里云天池大数据长期赛:金融风控-贷款违约预测(含代码)

本次比赛让自己在大数据的处理流程上有了更明确的认知,从数据清洗、特征工程、数据建模,每一个过程都能学到很多经验和知识,值得去历练。

weixin_46685991的博客 1万+

一文搞懂Netty中Handler的执行顺序

看了很多讲解Netty中InboundHandler、OutboundHandler执行顺序的文章,很少有一篇能完全讲的全的、对的、没有歧义的,在此根据所学、亲自验证得出的结论给大家举例:netty服务端是这个添加顺序 链表中的顺序为head->in1->in2->out1->out2->tail1、如果在InboundHandler2中执行的是ctx.channel().writeAndFlush,执行顺序是: 结果证明:执行完InboundHandler1、InboundHandler2之后,由

zhengchao1991的博客 8483

基于STM32的农业蔬菜大棚温湿度采集控制系统(代码+仿真+全部资料)

摘要: 本研究设计了一种基于STM32微控制器的农业蔬菜大棚温湿度智能控制系统。系统通过DHT11传感器实时采集温湿度数据,LCD屏显示当前值及预设阈值,用户可通过按键模块调整阈值范围。当温湿度超出设定阈值时,系统自动控制风扇或加湿器进行调节,确保大棚环境稳定。实验验证表明,该系统具备高精度监测、稳定控制和模块化扩展等优势,有效优化蔬菜生长环境。未来可扩展远程监控等功能,进一步提升智能化水平。 关键词: STM32、温湿度控制、蔬菜大棚、DHT11、自动化调节

3254968421的博客 785

复制幻灯片到另一个PPT编程

请确保将源PPT文件和目标PPT文件的文件名修改为你实际使用的文件名。运行上述代码后,目标PPT将包含源PPT中的所有幻灯片和形状。这里假设源PPT文件名为"source.pptx",目标PPT文件名为"target.pptx"。方法将每个幻灯片的布局添加到目标PPT中。是一个强大的库,可以用于创建、修改和操作PPT文件。要将一个PPT中的幻灯片复制到另一个PPT,可以使用Python的。这段代码遍历源PPT的每个幻灯片,并使用。步骤 3: 打开源PPT和目标PPT。这将保存修改后的目标PPT文件。

ByteSparkX的博客 1322

Netty学习——源码篇8 Outbound/Inbound传播方式

可以看到,ChannelOutboundHandlerAdapter的connect方法仅调用了ctx.connect方法,而这个调用又回到了Cotext.connect方法调用Connect.findContextOutbound方法,然后调用next.invokeConect方法,其次调用handler.connect方法,最后又调用Context.connect方法,如此循环下去,直到Connect事件传递到DefaultChannelPipeline的双向链表的头节点,即Head中。

geminigoth的博客 1168

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Netty框架之Pipeline中InboundHandler和OutboundHandler的执行顺序

我们假设现在的Pipeline中的Handler执行器链是这样的: Pipeline->h1->h2->h3->h4->h5->h6->tail 假设h1,h2,h3是ChannelInboudHadnler入栈处理器,h4,h5,h6是ChannelOutboundHandler出栈处理器 那么Handler的执行顺序是h1->h2->h3->h6->h5->h4,先执行InboundHandler,再反从tail往前找执行Outbo

TheWayForDream 1045

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

源码分析Netty中Handler的注册顺序问题

问题描述 ServerBootstrap注册了一个InboundHandler和一个OutboundHandler, 在InboundHandler调用了writeAndFlush,然后OutboundHandler的write方法不执行 原因 注册Handler时将InboundHandler置于OutboundHandler之前导致,应该调换顺序。 源码层面解析 当InboundHandler调用了writeAndFlush时,会调用AbstractChannelHandlerContext

ongnen的博客 240

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Netty中Pipeline的ChannelHandler执行顺序案例详解

1、InboundHandler是通过fire事件决定是否要执行下一个InboundHandler,如果哪个InboundHandler没有调用fire事件,那么往后的Pipeline就断掉了。2、InboundHandler是按照Pipleline的加载顺序,顺序执行。3、OutboundHandler是按照Pipeline的加载顺序,逆序执行。4、有效的InboundHandler是指通过fire事件能触达到的最后一个InboundHander。

小单的博客专栏 782

netty中ChannelHandler执行顺序案例详解

一、netty的Pipeline模型 netty的Pipeline模型用的是责任链设计模式,当boss线程监控到绑定端口上有accept事件,此时会为该socket连接实例化Pipeline,并将InboundHandler和OutboundHandler按序加载到Pipeline中,然后将该socket连接(也就是Channel对象)挂载到selector上。一个selector对应一个线程,该线程会轮询所有挂载在他身上的socket连接有没有read或write事件,然后通过线程池去执行Pipelin

入门菜鸟程序员的成长 1733

netty中Pipeline的ChannelHandler执行顺序案例详解

一、netty的Pipeline模型 netty的Pipeline模型用的是责任链 设计模式,当boss线程监控到绑定端口上有accept事件,此时会为该socket连接实例化Pipeline,并将InboundHandler和OutboundHandler按序加载到Pipeline中,然后将该socket连接(也就是Channel对象)挂载到selector上。一个selector对应一个线程,...

songfei_dream的专栏 3466

Netty中InboundHandler先注册OutboundHandler后注册为什么不会执行OutboundHandler

注册顺序 ch.pipeline().addLast(new InboundHandler1()); ch.pipeline().addLast(new InboundHandler2()); ch.pipeline().addLast(new OutboundHandler1()); ch.pipeline().addLast(new OutboundHandler2()); 入站时找 InboundHandler private AbstractChannelHandlerContext fi

qq_41963899的博客 565

netty 问题总结

netty支持的通讯协议(Channel )类型 参考:https://www.cnblogs.com/duanxz/p/3724432.html 不同协议不同的阻塞类型的连接都有不同的 Channel 类型与之对应下面是一些常用的 Channel 类型: NioSocketChannel, 代表异步的客户端 TCP Socket 连接. NioServerSocketChannel, 异步的服务器端 TCP Socket 连接. NioDatagramChannel, ...

FREEDOM 5584

Netty6:Channel、Pipeline、异步模型

1、Channel介绍 Channel是通讯的载体,ChannelHandler负责Channel中的逻辑处理; ChannelPipeline是ChannelHandler的容器,一个Channel包含一个ChannelPipeline,所有ChannelHandler都会注册到ChannelPipeline中,并按顺序组织起来; Netty中,ChannelEvent是数据或者状态的载体,传输数据对应MessageEvent,改变状态对应ChannelStateEvent,当对Channel操作时,会

Yisnow.的博客 539

六 学习netty之 handler的顺序

addLast里的handler 1.对于inbound, 执行顺序是注册顺序的顺序, 对于outbound,执行顺序是注册顺序的逆序 注意: 1.inboundHandler之间的传递需要fireChannelRead实现;调用ctx.write() 将传递到OutboundHandler ...

210

Netty PipeLine 注意事项总结

1、InboundHandler是通过fire事件决定是否要执行下一个InboundHandler,如果哪个InboundHandler没有调用fire事件,那么往后的Pipeline就断掉了。2、InboundHandler是按照Pipleline的加载顺序,顺序执行。3、OutboundHandler是按照Pipeline的加载顺序,逆序执行。4、有效的InboundHandler是指通过fire事件能触达到的最后一个InboundHander。

小单的博客专栏 620

关于Netty Pipeline中Handler的执行顺序问题

原文地址:http://blog.youkuaiyun.com/wgyvip/article/details/25637651 最近在学习Netty框架,根据官网的教程学着做了几个小测试,都成功了,后面开始试着写自己的应用的时候出了问题:Server发出的数据到达Client之后一直解码失败,折腾了好久,对比着官方的实例代码一步步走,最后终于在ChannelInitializer中发现了问题。原来我是这样写...

weixin_30247307的博客 305

什么是 Netty 的 ChannelPipeline,它是如何工作的?

pipeline 翻译为管道、流水线,在 Netty 这个大工厂中,ChannelPipeline 就像一条流水线,数据流过 ChannelPipeline,被一步一步地加工,最后得到一个成熟的工艺品。在 Netty 中,ChannelPipeline 是 Netty 的核心处理链,用于实现网络时间的动态编排和有序传播。它负责组织和编排各种 ChannelHandler,使他们能够有序地组织在一起,但实际的数据加工还是由 ChannelHandler 处理。

smart_an的专栏 1047

Netty(六) 初探Netty与Netty线程模型

1.为什么我们使用Netty NIO 的类库和 API 繁杂, 使用麻烦: 需要熟练掌握Selector、 ServerSocketChannel、 SocketChannel、 ByteBuffer等。 开发工作量和难度都非常大: 例如客户端面临断线重连、 网络闪断、心跳处理、半包读写、 网络拥塞和异常流的处理等等。 Netty 对 JDK 自带的 NIO 的 API 进行了良好的封装,解决了上述问题。且Netty拥有高性能、 吞吐量更高,延迟更低,减少资源消耗,最小化不必要的内存复制等优点。 ..

qq_24768941的博客 1104
上一篇: springboot之@Scheduled的使用
下一篇: 生信-记一次NCBI-R语言-淋巴癌突变与未突变基因的差异分析
lietobrain
博客等级 码龄11年 227粉丝 44原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值