惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
博客园 - 聂微东
Application and Cybersecurity Blog
Application and Cybersecurity Blog
MyScale Blog
MyScale Blog
罗磊的独立博客
H
Help Net Security
L
LangChain Blog
T
Threat Research - Cisco Blogs
量子位
S
Securelist
Last Week in AI
Last Week in AI
L
Lohrmann on Cybersecurity
T
The Exploit Database - CXSecurity.com
P
Privacy International News Feed
The Hacker News
The Hacker News
Vercel News
Vercel News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
T
Threatpost
Security Latest
Security Latest
P
Palo Alto Networks Blog
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
F
Full Disclosure
WordPress大学
WordPress大学
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Heimdal Security Blog
J
Java Code Geeks
Recorded Future
Recorded Future
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
阮一峰的网络日志
阮一峰的网络日志
U
Unit 42
B
Blog RSS Feed
月光博客
月光博客
C
Cisco Blogs
V
Visual Studio Blog
D
DataBreaches.Net
H
Hacker News: Front Page
博客园 - 叶小钗
N
News and Events Feed by Topic
爱范儿
爱范儿
A
Arctic Wolf

博客园 - 三驾马车

Claude Code 官宣:可以在 IDEA 用了! idea gitee 更新已取消 解决方案 ByteBuffer和ByteBuf区别 Marshalling.getProvidedMarshallerFactory("serial") 参数有那些 ProtobufVarint32FrameDecoder和ProtobufDecoder区别 protobuf 的 Varint 编码规范 ChannelInboundHandlerAdapter 的channelRead和channelReadComplete的区别 Unpooled.buffer()和Unpooled.copiedBuffer区别 ServerBootstrap 和Bootstrap 区别 childhandler 和 handler 区别 ChannelInitializer<SocketChannel> 的作用详解 ChannelHandlerAdapter 和 ChannelInboundHandlerAdapter 的区别 SimpleChannelInboundHandler 中的 messageReceived 和 channelRead0 ChannelHandlerAdapter 与 ChannelInboundHandler 的区别 Application run failed .ParserException: while parsing a block mapping in 'reader' openssl genrsa 自签名ssl证书 上传本地项目到新建git项目 save download pdf
netty initChannel ch.pipeline().addLast 先后顺序很重要
三驾马车 · 2025-05-20 · via 博客园 - 三驾马车

在 Netty 中,ChannelPipeline 的处理器(ChannelHandler)的 添加顺序(addLast 的顺序)会直接影响数据的处理流程,尤其是在 入站(Inbound) 和 出站(Outbound) 事件的传播方向上。以下是关键点解析:


1. Pipeline 的处理顺序

Netty 的 ChannelPipeline 是一个 双向链表,事件(如数据读取、写入)会按照处理器的添加顺序依次传递。

  • 入站事件(Inbound):从 head → 自定义处理器 → tail(即 addLast 的先后顺序)。

  • 出站事件(Outbound):从 tail → 自定义处理器 → head(即 addLast 的逆序)。

示例代码

ch.pipeline()
    .addLast("decoder", new StringDecoder())    

2. 入站事件(Inbound)的顺序影响

假设接收到数据 "Hello"

  1. StringDecoder:将 ByteBuf 解码为 String

  2. MyBusinessHandler:处理解码后的字符串。

如果顺序颠倒

ch.pipeline()
    .addLast("handler", new MyBusinessHandler()) 
  • 问题MyBusinessHandler 会直接收到原始的 ByteBuf,无法正确处理数据。


3. 出站事件(Outbound)的顺序影响

假设发送数据 "World"

  1. MyBusinessHandler:发出 String 类型数据。

  2. StringEncoder:将 String 编码为 ByteBuf

如果顺序颠倒

ch.pipeline()
    .addLast("encoder", new StringEncoder())     
  • 问题StringEncoder 会先于 MyBusinessHandler 处理数据,导致编码失败(因为业务处理器未先转换数据)。


4. 必须遵循的规则

  1. 解码器(Inbound)

    • 应放在业务处理器之前,确保数据先解码再处理。

    • 例如:ProtobufDecoderStringDecoder

  2. 编码器(Outbound)

    • 应放在业务处理器之后,确保业务数据先准备好再编码。

    • 例如:ProtobufEncoderStringEncoder

  3. 业务处理器

    • 通常放在编解码器之间,处理已解码的入站数据或准备出站数据。


5. 典型 Pipeline 配置示例

场景:处理 Protobuf 数据

执行顺序

  • 入站
    FrameDecoder → ProtobufDecoder → MyBusinessHandler

  • 出站
    MyBusinessHandler → ProtobufEncoder → LengthFieldPrepender


6. 调试技巧

如果处理器顺序不正确,可以通过以下方式排查:

  1. 打印 pipeline 的当前顺序:

    System.out.println(ch.pipeline().names());
  2. 检查日志中事件的传播路径,确保编解码器在正确位置。


7. 特殊处理器

  • SimpleChannelInboundHandler
    只处理特定类型的入站数据,需确保前置解码器已转换数据到目标类型。

  • ChannelDuplexHandler
    同时处理入站和出站事件,需谨慎安排顺序。


总结

  • 顺序很重要addLast 的先后顺序直接影响数据处理流程。

  • 入站:从前往后(解码 → 业务处理)。

  • 出站:从后往前(业务处理 → 编码)。

  • 黄金法则:编解码器靠近传输层,业务处理器靠近应用层。

如果遇到数据解析失败或编码错误,首先检查 Pipeline 的处理器顺序!