news 2026/4/23 13:17:50

Netty 学习记录:一个 CRUD 工程师的踩坑之旅

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Netty 学习记录:一个 CRUD 工程师的踩坑之旅

Netty 学习记录:一个 CRUD 工程师的踩坑之旅

这是一个小白的学习记录
边学边练,把踩过的坑都记下来


先说下我为什么要学 Netty

公司项目要做一个实时通讯系统,领导让我负责技术选型。拿到需求一看,好家伙,要支持数万并发连接,还要低延迟。

我之前也就写过点 Spring Boot 的 CRUD 代码,对网络编程一窍不通。网上的文档要么太深奥,要么太简单。没办法,只能自己一点点啃,顺便把学习笔记整理出来。

如果你也是新手,希望这篇笔记能帮到你。

我的技术水平

  • Java 能看懂(CRUD 工程师)
  • Linux 命令会用(cd、ls、vim 三件套)
  • 网络编程这东西我之前也就停留在"知道 TCP/IP"的 level

坑 1:环境搭建就踩坑

❌ 我当时以为很简单

刚开始学 Netty,我想着不就是加个依赖嘛,So easy!

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>5.0.0.Alpha2</version></dependency>

结果启动项目就报错:

Exception in thread "main" java.lang.NoClassDefFoundError: io/netty/util/concurrent/EventExecutorGroup

我当时就懵了。啥?EventExecutorGroup 是个啥?

🔍 问题根源

后来查资料才明白:

  1. Netty 5.x 版本是 alpha 版本,不稳定
  2. 很多依赖包版本不兼容
  3. 网上的教程大多用的是 4.x 版本

好家伙,原来是版本惹的祸。

✅ 解决方案

换成稳定的 4.x 版本:

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.87.Final</version></dependency>

教训:别用 alpha 版本!老老实实用稳定版。

坑 2:线程模型配置懵逼

❌ 我当时以为很简单

看了教程,说要创建两个 EventLoopGroup,我就随便写了:

EventLoopGroupbossGroup=newNioEventLoopGroup();EventLoopGroupworkerGroup=newNioEventLoopGroup();

结果运行起来,CPU 使用率直接爆表。

我当时就急了,老板在旁边看着,我满头汗。

🔍 问题根源

后来查资料才明白:

  1. 不指定线程数时,默认是 CPU 核心数的 2 倍
  2. bossGroup 只负责接受连接,不需要太多线程
  3. 我电脑 8 核,一下就创建了 16 个线程

✅ 解决方案

正确配置线程数:

// bossGroup 只需要 1 个线程EventLoopGroupbossGroup=newNioEventLoopGroup(1);// workerGroup 可以根据需要调整EventLoopGroupworkerGroup=newNioEventLoopGroup();

教训:线程数不是越多越好,要根据实际需求配置。

坑 3:粘包/拆包问题搞不定

❌ 我当时以为很简单

写了个 Echo 服务器,结果客户端发"Hello",服务器收到"HelloHelloHello",或者收到"Hel"、“lo”。

我当时就懵了,这是啥情况?数据怎么还能粘在一起?

🔍 问题根源

后来查资料才明白:

  1. TCP 是面向流的协议,数据会被分割或合并
  2. 这就是粘包/拆包问题
  3. 需要用解码器来处理

✅ 解决方案

使用 LengthFieldBasedFrameDecoder:

ch.pipeline().addLast(newLengthFieldBasedFrameDecoder(1024,// 最大帧长度0,// 长度字段偏移量4,// 长度字段长度0,// 长度调整值4// 跳过长度字段));ch.pipeline().addLast(newMessageToByteEncoder<String>(){@Overrideprotectedvoidencode(ChannelHandlerContextctx,Stringmsg,ByteBufout)throwsException{byte[]data=msg.getBytes();out.writeInt(data.length);out.writeBytes(data);}});

教训:网络编程一定要处理粘包/拆包问题!

坑 4:ByteBuf 内存泄漏

❌ 我当时以为很简单

写了个处理器,直接操作 ByteBuf:

@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){ByteBufbuf=(ByteBuf)msg;byte[]data=newbyte[buf.readableBytes()];buf.readBytes(data);Stringmessage=newString(data);System.out.println("Received: "+message);// 直接返回,没释放 buf}

结果运行一段时间后,程序崩溃,报 OutOfMemoryError。

🔍 问题根源

后来查资料才明白:

  1. ByteBuf 需要手动释放
  2. 特别是直接内存,不释放会导致内存泄漏
  3. 应该用 SimpleChannelInboundHandler,它会自动释放

✅ 解决方案

使用 SimpleChannelInboundHandler:

publicclassMyHandlerextendsSimpleChannelInboundHandler<String>{@OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,Stringmsg){System.out.println("Received: "+msg);// 不用手动释放,SimpleChannelInboundHandler 会自动处理}}

教训:ByteBuf 一定要记得释放,或者用 SimpleChannelInboundHandler。

验证步骤

1. 编译打包

mvn clean package

2. 启动服务端

java-jar netty-server.jar

3. 启动客户端

java-jar netty-client.jar

4. 测试消息发送

在客户端输入消息,确认服务端能正确接收并回显。

预期结果:消息能正确发送和接收,没有粘包/拆包问题。

总结

我踩过的坑

  1. 坑 1:用了不稳定的 Netty 5.x 版本 → 换成 4.1.87.Final
  2. 坑 2:线程数配置不当 → bossGroup 设为 1,workerGroup 默认
  3. 坑 3:没处理粘包/拆包问题 → 使用 LengthFieldBasedFrameDecoder
  4. 坑 4:ByteBuf 内存泄漏 → 使用 SimpleChannelInboundHandler

核心要点

  • 必须用稳定版本:Netty 4.1.x 是稳定版
  • 必须配置线程数:bossGroup 1 个线程足够
  • 必须处理粘包/拆包:使用合适的解码器
  • 必须注意内存管理:使用 SimpleChannelInboundHandler 或手动释放 ByteBuf

最后说两句

其实 Netty 也没多难,就是刚开始上手的时候有点懵。我也是一点点试,总算是搞定了基础的 Echo 服务器。

肯定有理解不对的地方,欢迎大佬指正。

如果你也遇到类似问题,希望这篇笔记能帮到你。


小技巧:学习 Netty 最好的方法就是跟着官方示例写代码,遇到问题就查文档。别想着一步到位,慢慢来,总能学会的!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 6:00:27

RTCP 反馈的详细格式

RTCP 反馈消息是 RTP/AVPF 配置文件(RFC 4585)定义的核心扩展机制,它让接收端能够及时地向发送端报告丢包、带宽估计、关键帧请求等信息,从而实现实时通信中的拥塞控制和错误恢复。 一、整体结构概览 所有的 RTCP 反馈消息都遵循通用 RTCP 包头 + 反馈控制信息的结构。 c…

作者头像 李华