【Netty源码解读和权威指南】第32篇:Netty背压机制——不让发送方“撑死“接收方

📅 2026/6/21 6:01:36
【Netty源码解读和权威指南】第32篇:Netty背压机制——不让发送方“撑死“接收方
上一篇【第31篇】Netty零拷贝深度解析——性能极致的秘密武器下一篇【第33篇】Netty连接管理与心跳检测——工业级断连处理方案开篇故事某支付系统生产者TQ是消费者的10倍结果消费者OOM了——消息发送太快来不及处理背压Back Pressure下游处理不过来时通知上游减速。Netty天然支持背压通过ChannelOutboundBuffer的水位线TCP滑动窗口。一、背压的TCP层基础TCP滑动窗口 发送方 接收方 | | |--数据1~1000------------------| |--数据1001~2000---------------| | 接收窗口满 |-------ACK(win0)------------| ← 窗口为0暂停发送 | 处理完成 |-------ACK(win5000)---------| ← 窗口恢复继续发送 |--数据2001~3000---------------|二、Netty应用层背压2.1 水位线机制// 默认配置writeBufferHighWaterMark64KB// 高水位writeBufferLowWaterMark32KB// 低水位// 状态转换if(pendingByteshighWaterMarkwritable){writablefalse;// 不可写fireChannelWritabilityChanged();// 触发事件}if(pendingByteslowWaterMark!writable){writabletrue;// 可写fireChannelWritabilityChanged();// 触发事件}2.2 背压处理HandlerpublicclassBackPressureHandlerextendsChannelInboundHandlerAdapter{privatevolatilebooleanpaused;privateQueueObjectbuffernewConcurrentLinkedQueue();OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){if(paused){buffer.offer(msg);// 暂存}else{ctx.fireChannelRead(msg);// 正常传播}// 发送响应并检查水位线ChannelFuturefctx.writeAndFlush(process(msg));if(!ctx.channel().isWritable()){f.addListener(future-{pausedtrue;// 暂停从上游拉取数据upstreamSource.pause();});}}OverridepublicvoidchannelWritabilityChanged(ChannelHandlerContextctx){if(ctx.channel().isWritable()){pausedfalse;upstreamSource.resume();// 处理积压消息Objectmsg;while((msgbuffer.poll())!null){ctx.fireChannelRead(msg);}}ctx.fireChannelWritabilityChanged();}}三、实战带背压的代理服务器publicclassBackPressureProxyextendsChannelInboundHandlerAdapter{privateChannelbackendChannel;privatebooleanfrontendPaused;OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){if(backendChannel!nullbackendChannel.isActive()){backendChannel.writeAndFlush(msg).addListener(f-{// 检查后端是否满if(!backendChannel.isWritable()!frontendPaused){frontendPausedtrue;ctx.channel().config().setAutoRead(false);// 暂停读前端}});}}OverridepublicvoidchannelWritabilityChanged(ChannelHandlerContextctx){if(ctx.channel().isWritable()frontendPaused){frontendPausedfalse;ctx.channel().config().setAutoRead(true);// 恢复读前端}ctx.fireChannelWritabilityChanged();}}四、背压链路图客户端→Netty前端Handler→Netty后端Handler→下游服务 ↑ ↑ autoReadfalse channelWritabilityChanged (暂停读取) (恢复读取) | | --------→ 水位线触发 ←-------------五、总结层级机制TCP层滑动窗口窗口0时自动暂停发送Netty应用层writeBufferWaterMark channelWritabilityChanged业务层autoRead(false)暂停读业务处理完后恢复上一篇【第31篇】Netty零拷贝深度解析——性能极致的秘密武器下一篇【第33篇】Netty连接管理与心跳检测——工业级断连处理方案