在处理流量限速,流量整形方面令牌桶算法是一个有效的解决方案,不过在对于应用程序适应网络中大流量高性能的场景,经常会使用到网卡多队列并绑定多核CPU处理以提高性能,更好的处理网络流量。多核之间的数据往往是独立,如果要共享一个令牌桶又容易出现竞争加锁又可能导致性能大幅下降而偏离原来高性能处理的初衷。
所以我们使用一种创建一个逻辑共享的令牌桶,实际又是每个核拥有一个独立的令牌桶来解决多核多队列场景下Qos限速的问题。
实现原理:
为每一个pps/bps阈值的配置设置一个令牌桶,以udp数据包的pps为例,设置限速阈值为60000 , bps为0 (不启用令牌桶)
程序加载配置后为udp 逻辑上创建一个令牌桶,桶深度size为60000,桶的初始令牌token为60000,桶的令牌生产速率rate为每秒60000,当udp的流量到达阈值60000后,
流量进入令牌桶,计算上一次时钟周期数,与当前时钟周期差值,换算成时间秒乘以令牌桶生产速率60000为新产生的令牌,加入令牌桶,如果桶满则最大60000
如果令牌数大于1(或bps数据包的长度pkt_len*8)则报文通过,令牌减1(或bps数据包的长度pkt_len*8),否则报文不能通过令牌桶(丢弃或其他动作)。
由于抗D数据会分发到多个业务核(N个),则实际上必须为每个核创建一个令牌桶,初始化桶的深度和生产速率为60000/N,每秒钟再根据每个业务核的流量占比动态调整各个核的令牌桶深度与生产速率来达到整体限速打到阈值配置的效果。
每个核统计经过本核的流量traffic1,traffic2, trafficN并计算所有核流量traffic得到流量占比traffcN/traffic
定时器根据流量占比重新调整令牌桶的深度size与令牌生产速率rate = 60000*traffcN/traffic。