Netty实战:手把手教你实现一个高可用的TCP长连接服务(附完整代码+避坑指南)
视频看了几百小时还迷糊关注我几分钟让你秒懂发点评论可以给博主加热度哦一、为什么用 Netty真实业务场景解析在物联网IoT、金融交易、游戏服务器、即时通讯等场景中高并发、低延迟、稳定可靠的 TCP 长连接是刚需。 场景智能设备上报数据10万台设备通过 TCP 连接服务器每秒上报位置、电量、状态等信息服务器需实时处理并下发指令如“重启”、“升级”传统 Java BIOBlocking IO方案ServerSocket server new ServerSocket(8080); while (true) { Socket socket server.accept(); // 阻塞 new Thread(() - handle(socket)).start(); // 每连接开一线程 }❌ 问题线程数爆炸10万连接 10万线程上下文切换开销大内存耗尽、系统崩溃Netty 方案Reactor 模型✅ 优势单线程可处理数万连接基于 NIO 事件驱动内存池、零拷贝优化性能自带心跳、粘包/拆包、重连等机制二、Spring Boot Netty 快速搭建 TCP 服务正确姿势 注意Netty 是独立于 Spring 的网络框架但可无缝集成到 Spring Boot 项目中。第一步添加依赖pom.xmldependency groupIdio.netty/groupId artifactIdnetty-all/artifactId version4.1.100.Final/version /dependency !-- 可选用于优雅关闭 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency第二步定义消息协议解决粘包/拆包我们采用长度字段 JSON的自定义协议| 4字节长度 | JSON字符串 | |-----------|------------| | 00 00 00 1C | {cmd:login,data:{id:D1001}} |✅ 为什么不用纯文本因为 TCP 是流式协议不保证消息边界必须定义协议第三步编写消息编解码器1. 消息实体类public class TcpMessage { private String cmd; // 指令login, heartbeat, data private Object data; // 负载数据 // getter/setter/toString 略 }2. 编码器Java对象 → 字节流public class MessageEncoder extends MessageToByteEncoderTcpMessage { Override protected void encode(ChannelHandlerContext ctx, TcpMessage msg, ByteBuf out) { try { String json new ObjectMapper().writeValueAsString(msg); byte[] bytes json.getBytes(StandardCharsets.UTF_8); out.writeInt(bytes.length); // 写入4字节长度 out.writeBytes(bytes); // 写入JSON内容 } catch (Exception e) { throw new RuntimeException(编码失败, e); } } }3. 解码器字节流 → Java对象public class MessageDecoder extends LengthFieldBasedFrameDecoder { public MessageDecoder() { super( 1024 * 1024, // maxFrameLength 最大帧长度 0, // lengthFieldOffset 长度字段偏移 4, // lengthFieldLength 长度字段占4字节 0, // lengthAdjustment 4 // initialBytesToStrip 跳过长度字段 ); } Override protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { ByteBuf frame (ByteBuf) super.decode(ctx, in); if (frame null) return null; try { byte[] bytes new byte[frame.readableBytes()]; frame.readBytes(bytes); String json new String(bytes, StandardCharsets.UTF_8); return new ObjectMapper().readValue(json, TcpMessage.class); } finally { frame.release(); } } }第四步实现业务处理器Component ChannelHandler.Sharable // 标记为可共享避免每次新建 public class TcpServerHandler extends SimpleChannelInboundHandlerTcpMessage { private static final Logger log LoggerFactory.getLogger(TcpServerHandler.class); Override public void channelActive(ChannelHandlerContext ctx) { log.info(设备上线: {}, ctx.channel().remoteAddress()); // 可在此记录连接、分配ID等 } Override public void channelInactive(ChannelHandlerContext ctx) { log.info(设备离线: {}, ctx.channel().remoteAddress()); // 清理资源、标记离线 } Override protected void channelRead0(ChannelHandlerContext ctx, TcpMessage msg) { log.info(收到消息: {}, msg); // 根据指令处理 switch (msg.getCmd()) { case login: handleLogin(ctx, msg); break; case heartbeat: // 心跳直接回复 ctx.writeAndFlush(new TcpMessage(ack, ok)); break; case data: handleData(ctx, msg); break; default: ctx.writeAndFlush(new TcpMessage(error, unknown command)); } } private void handleLogin(ChannelHandlerContext ctx, TcpMessage msg) { // 模拟登录验证 String deviceId ((MapString, String) msg.getData()).get(id); log.info(设备 {} 登录成功, deviceId); ctx.writeAndFlush(new TcpMessage(login_ack, success)); } private void handleData(ChannelHandlerContext ctx, TcpMessage msg) { // 处理业务数据 ctx.writeAndFlush(new TcpMessage(data_ack, received)); } Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { log.error(连接异常: {}, ctx.channel().remoteAddress(), cause); ctx.close(); // 出错关闭连接 } }第五步启动 Netty 服务集成到 Spring BootComponent public class NettyTcpServer { private static final Logger log LoggerFactory.getLogger(NettyTcpServer.class); private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; private Channel serverChannel; Autowired private TcpServerHandler tcpServerHandler; PostConstruct public void start() throws InterruptedException { bossGroup new NioEventLoopGroup(1); workerGroup new NioEventLoopGroup(); ServerBootstrap bootstrap new ServerBootstrap() .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializerSocketChannel() { Override protected void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new MessageDecoder()) .addLast(new MessageEncoder()) .addLast(tcpServerHandler); // 业务处理器 } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); serverChannel bootstrap.bind(8080).sync().channel(); log.info(Netty TCP 服务已启动监听端口: 8080); } PreDestroy public void stop() { if (serverChannel ! null) { serverChannel.close(); } if (bossGroup ! null) { bossGroup.shutdownGracefully(); } if (workerGroup ! null) { workerGroup.shutdownGracefully(); } log.info(Netty TCP 服务已关闭); } }✅ 关键点使用PostConstruct启动PreDestroy优雅关闭ChannelHandler.Sharable避免重复创建 Handler 实例三、客户端测试代码模拟设备public class TcpClientTest { public static void main(String[] args) throws Exception { EventLoopGroup group new NioEventLoopGroup(); try { Bootstrap bootstrap new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializerSocketChannel() { Override protected void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new MessageDecoder()) .addLast(new MessageEncoder()) .addLast(new SimpleChannelInboundHandlerTcpMessage() { Override protected void channelRead0(ChannelHandlerContext ctx, TcpMessage msg) { System.out.println(收到服务端回复: msg); } }); } }); Channel channel bootstrap.connect(localhost, 8080).sync().channel(); // 发送登录 TcpMessage loginMsg new TcpMessage(); loginMsg.setCmd(login); loginMsg.setData(Map.of(id, D1001)); channel.writeAndFlush(loginMsg); // 发送心跳 TcpMessage hb new TcpMessage(); hb.setCmd(heartbeat); hb.setData(ping); channel.writeAndFlush(hb); // 保持连接 Thread.sleep(5000); channel.closeFuture().sync(); } finally { group.shutdownGracefully(); } } }四、常见反例 避坑指南新手必看❌ 反例1未处理粘包/拆包 → 消息解析错乱// 错误直接按行读取只适用于 \n 分隔的文本协议 ch.pipeline().addLast(new LineBasedFrameDecoder(1024));✅ 正确使用LengthFieldBasedFrameDecoder或自定义协议头❌ 反例2Handler 不加Sharable→ 内存泄漏// 每次连接都 new 一个 Handler持有上下文引用无法释放 .childHandler(new ChannelInitializer...() { protected void initChannel(...) { ch.pipeline().addLast(new TcpServerHandler()); // ❌ } });✅ 正确注入 Spring Bean 并标记Sharable❌ 反例3未设置 SO_KEEPALIVE → 僵尸连接堆积// 默认不开启 TCP 心跳断网后连接仍“假在线” .childOption(ChannelOption.SO_KEEPALIVE, false); // ❌✅ 正确.childOption(ChannelOption.SO_KEEPALIVE, true); // 或应用层实现心跳更可靠❌ 反例4异常未关闭连接 → 资源泄露Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // 什么都不做连接会一直挂着 }✅ 正确捕获异常后ctx.close()五、生产环境增强建议功能实现方式心跳检测客户端定时发heartbeat服务端记录最后活跃时间超时踢出连接管理用ConcurrentHashMapString, Channel存储设备ID与Channel映射SSL加密添加SslHandler到 pipeline流量控制使用ChannelOption.WRITE_BUFFER_WATER_MARK监控指标暴露连接数、吞吐量等指标到 Prometheus六、总结Netty 强大但复杂协议设计 代码实现。本文带你✅ 从零搭建 Spring Boot Netty TCP 服务✅ 解决粘包/拆包、连接管理、异常处理等核心问题✅ 避开内存泄漏、僵尸连接等致命陷阱记住高并发不是堆机器而是靠合理架构。Netty 是你构建高性能网络服务的基石视频看了几百小时还迷糊关注我几分钟让你秒懂发点评论可以给博主加热度哦

相关新闻

集成双 5W 功放 + AI 降噪!WX-0813 语音模组让全场景通话体验翻倍

集成双 5W 功放 + AI 降噪!WX-0813 语音模组让全场景通话体验翻倍

在智能设备爆发的当下,语音交互已成为核心需求之一,但环境噪音、通话回音、音频电路复杂等问题却一直困扰着开发者。无论是车载通话的风噪干扰、会议设备的多人回音,还是安防监控的环境杂音,都严重影响语音传输的清晰度。今天给大…

2026/7/3 14:45:30 阅读更多 →
6.3 Istio流量管理实战:实现Bookinfo的灰度发布和A B测试

6.3 Istio流量管理实战:实现Bookinfo的灰度发布和A B测试

6.3 Istio流量管理实战:实现Bookinfo的灰度发布和A/B测试 引言 Bookinfo是学习Istio流量管理的绝佳示例。通过Bookinfo可以实现灰度发布、A/B测试等高级流量管理功能。本文将详细介绍如何使用Istio管理Bookinfo的流量。 一、版本管理 1.1 定义版本 apiVersion: networkin…

2026/7/3 14:45:31 阅读更多 →
写作压力小了,AI论文软件 千笔·专业论文写作工具 VS 万方智搜AI

写作压力小了,AI论文软件 千笔·专业论文写作工具 VS 万方智搜AI

随着人工智能技术的迅猛迭代与普及,AI辅助写作工具已逐步渗透到高校学术写作场景中,成为专科生、本科生、研究生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生,开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时…

2026/7/3 14:45:35 阅读更多 →

最新新闻

WSaiOS:一种基于确定性-概率混合架构的AI语义能力模拟系统

WSaiOS:一种基于确定性-概率混合架构的AI语义能力模拟系统

WSaiOS:一种基于确定性-概率混合架构的AI语义能力模拟系统作者:东塬一老翁发表时间:2026年7月4日版本:1.0---摘要随着大语言模型(LLM)在自然语言处理领域的广泛应用,其高昂的计算成本、低可解释…

2026/7/4 13:45:30 阅读更多 →
PHP源码保护实战:从混淆加密到授权系统的2024一体化方案

PHP源码保护实战:从混淆加密到授权系统的2024一体化方案

1. 项目概述与核心需求解析 “2024 首发 PHP加密系统php源码”这个标题,乍一看像是某个资源分享站点的标题,但背后折射出的,其实是PHP开发者、项目管理者以及商业软件供应商们一个持续了二十多年的核心痛点: 如何保护自己的PHP源…

2026/7/4 13:45:30 阅读更多 →
15A无刷电机FOC控制:硬件选型与算法优化实践

15A无刷电机FOC控制:硬件选型与算法优化实践

1. 项目背景与核心挑战在工业自动化、无人机和电动汽车等领域,无刷直流电机(BLDC)因其高效率、长寿命和低维护需求而广受欢迎。然而,实现高性能的BLDC控制并非易事,尤其是当电流需求高达15A时,工程师们面临…

2026/7/4 13:39:25 阅读更多 →
三维机动目标跟踪:IMM+UKF算法实战解析

三维机动目标跟踪:IMM+UKF算法实战解析

1. 三维机动目标跟踪的挑战与IMMUKF方案 在目标跟踪领域,三维机动目标的跟踪一直是个棘手问题。我做了八年多的目标跟踪算法开发,最深的体会就是:目标一动不如一静,特别是当目标突然改变运动状态时,传统单模型滤波器的…

2026/7/4 13:37:25 阅读更多 →
基于计算机视觉的视线检测:从MediaPipe实现到自动化触发

基于计算机视觉的视线检测:从MediaPipe实现到自动化触发

1. 先搞清楚“当你突然看我的时候”到底在解决什么问题“当你突然看我的时候”这个标题,乍一看不像一个技术项目,更像一句文艺的句子。但如果你在技术社区、开源平台或者开发者论坛里看到它,它大概率指向一个特定的、需要技术手段来解决的场景…

2026/7/4 13:37:24 阅读更多 →
基于YOLO与SpringBoot的葡萄叶片病害智能检测系统开发

基于YOLO与SpringBoot的葡萄叶片病害智能检测系统开发

1. 项目概述:葡萄叶片病害智能检测系统 去年夏天,我在宁夏某葡萄种植基地亲眼目睹了黑腐病爆发带来的惨重损失——短短两周内,30亩优质葡萄园减产近半。这让我深刻意识到,传统依赖人工经验的病害识别方式已经无法满足现代农业的需…

2026/7/4 13:33:18 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻