性能之巅:大小水管问题深究
文章目录
- 一、背景
- 二、大小水管问题
- 2.1 场景1: 报文转发
- 2.2 场景2: 进程间通信
- 三、解决方案
- 3.1 解决接收端阻塞
- 3.2 发送端流控: 速率匹配
- 3.3 突发流量: 队列长度调整
一、背景
在高性能服务器内部架构以及网络带宽优化中,经常会遇到大小水管问题,狭义的大小水管问题指流量转发中发送端和接收端速率不匹配导致丢包,从而引发吞吐量降低等一系列问题,广义上的大小水管即一切生产者消费者模型中,生产者速率大于消费者速率即大小水管。大小水管问题是性能优化中比较棘手的问题,本文从常规问题说明、原因和影响分析、解决方案几个方面介绍大小水管问题。
二、大小水管问题
2.1 场景1: 报文转发
发送端2.5G速率,接收端1G速率,必然会导致传输路径上出现丢包,由于流控机制,二层pause帧、tcp层流控机制,会将发送端速率压到1G。
流控机制有如下问题:
- 矫枉过正,可能会导致速率低于1G,突发流量
- 突发流量,可能存在瞬时流量超过接收端导致丢包。此时可以增加队列缓冲,缓冲瞬时突发流量。
2.2 场景2: 进程间通信
服务器架构中,进程间通信方式socket、pipe等队列也可能由于生产者大于消费者速率,导致丢包。进程间通信,一般看重的丢包,而不是吞吐量,直接表现可能是某些控制报文丢失,导致功能异常。可以从队列和接收端进行优化。
三、解决方案
优化方案从数据路径上的3个对象进行优化:
对象 | 优化手段 |
---|---|
接收端 | 算力匹配睡眠优化上下文分离 |
中间队列 | 缓冲突发流量队列长度扩展 |
发送端 | 流控机制,速率匹配 |
3.1 解决接收端阻塞
接收端接收不过来时,可能有如下原因:
- 睡眠问题
有某些sleep操作或者等待获取锁的主动睡眠操作,导致长时间无法处理报文,从而导致丢包。此时需要考虑将主动睡眠操作异步处理,锁优化需要分析锁的范围是否超标做无锁话处理。
- 算力匹配
确认是否是接收端算力太差,比如发送端是双核处理,接收端单核处理。发送端多线程,接收端单线程。 接收端考虑利用多线程、多核处理。
- 上下文优化
无锁处理以及睡眠优化等可以利用上下文优化进行,进行分割上下文,另起线程处理耗时久的任务以及持锁操作。
3.2 发送端流控: 速率匹配
利用反馈机制,将接收端的能力通知发送端,从而匹配速率,发送端按照接收端的速率发送。常见的流控机制和反馈方式如下:
流控方式 | 机制 | 反馈方式 |
---|---|---|
二层 | pause帧 | 接收端队列情况,直接上报。 |
三层 | tcp流控,滑动窗口 | 丢包情况,发送端间接探测。 |
3.3 突发流量: 队列长度调整
利用流控机制,并且引入中间队列处理突发流量,可以让发送端速率有无流控,流控的目的是将发送端尽量和接收端速率进行匹配,发送端按照接收端的速率发送。属于一个反馈机制,如TCP需要通过丢包等进行反馈,可能存在突发流量,瞬时出现大小水管,此时需要通过队列进行缓冲突发流量,保证不丢包,丢包对性能的影响是巨大的。
缓冲队列需要设置多少合适? 根据突发流量的吞吐量差值可计算出可以缓冲的突发流量时间。
缓冲时间 = 队列长度 / (发送端速率-接收端速率)