【Netty源码解读和权威指南】第37篇:Netty流量整形——优雅控制客户端发送速率
上一篇【第36篇】Netty时间轮高级应用——10亿级定时任务的工程实践
下一篇【第38篇】Netty SSL TLS安全传输——HTTPS背后的Netty实现
一、为什么需要流量整形?
某支付系统,上游每天凌晨批量同步数据,带宽被占满,影响正常交易。
流量整形:平滑流量,避免突发压垮下游。
二、原理:令牌桶算法
令牌桶:容量10 每秒产生5个令牌 时刻0: [T][T][T][T][T][_][_][_][_][_] (5个令牌) 发送3个包 → [T][T][_][_][_][_][_][_][_][_] (剩2个令牌) 时刻1: [T][T][T][T][T][T][T][_][_][_] (补充5个,共7个) 发送6个包 → [T][_][_][_][_][_][_][_][_][_] (剩1个令牌) 发送4个包 → [T][_][_][_][_][_][_][_][_][_] ↑ 只有1个令牌,只发送1个,3个等待!三、GlobalTrafficShapingHandler
// 全局流量整形:所有Channel共享带宽pipeline.addLast(newGlobalTrafficShapingHandler(eventExecutor,1024*1024,// writeLimit: 1MB/s 写速率1024*1024,// readLimit: 1MB/s 读速率1000// checkInterval: 1秒检查一次));// 源码核心:AbstractTrafficShapingHandler// 计算等待时间,延迟发送longwait=trafficCounter.readTimeToWait(size,limit,interval);if(wait>0){ctx.executor().schedule(()->{ctx.write(msg,promise);},wait,TimeUnit.MILLISECONDS);}四、ChannelTrafficShapingHandler
// 每个Channel独立限速pipeline.addLast(newChannelTrafficShapingHandler(512*1024,// 每个连接512KB/s0// 不限读));五、实战:防DDoS连接限流
publicclassAntiDdosHandlerextendsChannelInboundHandlerAdapter{privatefinalGlobalTrafficShapingHandlertrafficHandler;privatefinalAtomicIntegerconnections=newAtomicInteger();privatestaticfinalintMAX_CONNECTIONS=10000;publicAntiDdosHandler(EventExecutorexecutor){trafficHandler=newGlobalTrafficShapingHandler(executor,1024*1024,0);}@OverridepublicvoidchannelActive(ChannelHandlerContextctx){if(connections.incrementAndGet()>MAX_CONNECTIONS){System.out.println("连接数超限,拒绝新连接");ctx.close();}else{ctx.pipeline().addFirst(trafficHandler);ctx.fireChannelActive();}}@OverridepublicvoidchannelInactive(ChannelHandlerContextctx){connections.decrementAndGet();ctx.fireChannelInactive();}}六、对比总结
| Handler | 范围 | 配置 |
|---|---|---|
GlobalTrafficShapingHandler | 所有Channel共享 | writeLimit=1MB/s |
ChannelTrafficShapingHandler | 单个Channel独立 | writeLimit=512KB/s |
GlobalChannelTrafficShapingHandler | 全局+单Channel双重控制 | 灵活组合 |
上一篇【第36篇】Netty时间轮高级应用——10亿级定时任务的工程实践
下一篇【第38篇】Netty SSL TLS安全传输——HTTPS背后的Netty实现
