Netty 学习记录一个 CRUD 工程师的踩坑之旅这是一个小白的学习记录边学边练把踩过的坑都记下来先说下我为什么要学 Netty公司项目要做一个实时通讯系统领导让我负责技术选型。拿到需求一看好家伙要支持数万并发连接还要低延迟。我之前也就写过点 Spring Boot 的 CRUD 代码对网络编程一窍不通。网上的文档要么太深奥要么太简单。没办法只能自己一点点啃顺便把学习笔记整理出来。如果你也是新手希望这篇笔记能帮到你。我的技术水平Java 能看懂CRUD 工程师Linux 命令会用cd、ls、vim 三件套网络编程这东西我之前也就停留在知道 TCP/IP的 level坑 1环境搭建就踩坑❌ 我当时以为很简单刚开始学 Netty我想着不就是加个依赖嘛So easydependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion5.0.0.Alpha2/version/dependency结果启动项目就报错Exception in thread main java.lang.NoClassDefFoundError: io/netty/util/concurrent/EventExecutorGroup我当时就懵了。啥EventExecutorGroup 是个啥 问题根源后来查资料才明白Netty 5.x 版本是 alpha 版本不稳定很多依赖包版本不兼容网上的教程大多用的是 4.x 版本好家伙原来是版本惹的祸。✅ 解决方案换成稳定的 4.x 版本dependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.87.Final/version/dependency教训别用 alpha 版本老老实实用稳定版。坑 2线程模型配置懵逼❌ 我当时以为很简单看了教程说要创建两个 EventLoopGroup我就随便写了EventLoopGroupbossGroupnewNioEventLoopGroup();EventLoopGroupworkerGroupnewNioEventLoopGroup();结果运行起来CPU 使用率直接爆表。我当时就急了老板在旁边看着我满头汗。 问题根源后来查资料才明白不指定线程数时默认是 CPU 核心数的 2 倍bossGroup 只负责接受连接不需要太多线程我电脑 8 核一下就创建了 16 个线程✅ 解决方案正确配置线程数// bossGroup 只需要 1 个线程EventLoopGroupbossGroupnewNioEventLoopGroup(1);// workerGroup 可以根据需要调整EventLoopGroupworkerGroupnewNioEventLoopGroup();教训线程数不是越多越好要根据实际需求配置。坑 3粘包/拆包问题搞不定❌ 我当时以为很简单写了个 Echo 服务器结果客户端发Hello服务器收到HelloHelloHello或者收到Hel、“lo”。我当时就懵了这是啥情况数据怎么还能粘在一起 问题根源后来查资料才明白TCP 是面向流的协议数据会被分割或合并这就是粘包/拆包问题需要用解码器来处理✅ 解决方案使用 LengthFieldBasedFrameDecoderch.pipeline().addLast(newLengthFieldBasedFrameDecoder(1024,// 最大帧长度0,// 长度字段偏移量4,// 长度字段长度0,// 长度调整值4// 跳过长度字段));ch.pipeline().addLast(newMessageToByteEncoderString(){Overrideprotectedvoidencode(ChannelHandlerContextctx,Stringmsg,ByteBufout)throwsException{byte[]datamsg.getBytes();out.writeInt(data.length);out.writeBytes(data);}});教训网络编程一定要处理粘包/拆包问题坑 4ByteBuf 内存泄漏❌ 我当时以为很简单写了个处理器直接操作 ByteBufOverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){ByteBufbuf(ByteBuf)msg;byte[]datanewbyte[buf.readableBytes()];buf.readBytes(data);StringmessagenewString(data);System.out.println(Received: message);// 直接返回没释放 buf}结果运行一段时间后程序崩溃报 OutOfMemoryError。 问题根源后来查资料才明白ByteBuf 需要手动释放特别是直接内存不释放会导致内存泄漏应该用 SimpleChannelInboundHandler它会自动释放✅ 解决方案使用 SimpleChannelInboundHandlerpublicclassMyHandlerextendsSimpleChannelInboundHandlerString{OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,Stringmsg){System.out.println(Received: msg);// 不用手动释放SimpleChannelInboundHandler 会自动处理}}教训ByteBuf 一定要记得释放或者用 SimpleChannelInboundHandler。验证步骤1. 编译打包mvn clean package2. 启动服务端java-jar netty-server.jar3. 启动客户端java-jar netty-client.jar4. 测试消息发送在客户端输入消息确认服务端能正确接收并回显。预期结果消息能正确发送和接收没有粘包/拆包问题。总结我踩过的坑坑 1用了不稳定的 Netty 5.x 版本 → 换成 4.1.87.Final坑 2线程数配置不当 → bossGroup 设为 1workerGroup 默认坑 3没处理粘包/拆包问题 → 使用 LengthFieldBasedFrameDecoder坑 4ByteBuf 内存泄漏 → 使用 SimpleChannelInboundHandler核心要点必须用稳定版本Netty 4.1.x 是稳定版必须配置线程数bossGroup 1 个线程足够必须处理粘包/拆包使用合适的解码器必须注意内存管理使用 SimpleChannelInboundHandler 或手动释放 ByteBuf最后说两句其实 Netty 也没多难就是刚开始上手的时候有点懵。我也是一点点试总算是搞定了基础的 Echo 服务器。肯定有理解不对的地方欢迎大佬指正。如果你也遇到类似问题希望这篇笔记能帮到你。小技巧学习 Netty 最好的方法就是跟着官方示例写代码遇到问题就查文档。别想着一步到位慢慢来总能学会的