04.06 流量与拥塞控制:慢设备和网络瓶颈怎样拖慢 IM
返回第四卷 · 传输前置:04.04 · 连接前置:04.05 · 有界队列:05.03
04.06 流量与拥塞控制:慢设备和网络瓶颈怎样拖慢 IM
DeepTutor 初稿经技术与教学审阅后的静态课程。速率、窗口、队列、RTT 与延迟都是虚构纸上数值;本次没有运行 Go、抓包、压测、IM 服务或站点,也不据此评价 OpenIM 的实际性能。
一、B 收消息变慢:设备读不动,还是路上堵了
虚构 u-a 向 c-a 发送 m-a,服务端要把会话消息送给 u-b 的设备。A 看到“发送后 B 很久才有显示”,可能有两种不同限制:B 的应用处理很慢,接收缓冲逐渐满;或者A 到 B 的网络路径有瓶颈,包在中间排队、丢失或重传。二者都可能让发送端暂时不能继续发字节,却该看不同证据。不能只看到“长连接在线”和一次慢请求,就把原因归为“网络差”或“用户手机卡”。
网关业务出站队列 → TCP 发送缓冲 → 网络路径中的队列 → B 的 TCP 接收缓冲 → B 的 IM 应用读取
↑拥塞窗口 cwnd ↑路径瓶颈 ↑接收窗口 rwnd04.04 用一个“最多 8 字节在途”的窗口介绍流水线;现在把它分成两种约束。接收窗口 rwnd是接收端告诉发送端“我目前还能接多少字节”,保护慢接收方。拥塞窗口 cwnd由发送方的 TCP 拥塞控制维护,限制它向网络路径放入多少尚未确认字节。它们只管理这条 TCP 连接的字节流;网关应用队列、数据库持久化、B 设备展示与已读仍需各自的设计和证据。
| 第一遍 | 第二遍 | 交付物 |
|---|---|---|
rwnd、cwnd 与单位 | BDP、排队尾延迟、应用背压与诊断 | 两份瓶颈时间线、一页纸上预算、一张业务策略表 |
二、接收窗口 rwnd:B 的缓冲不是无限仓库
TCP 接收端有有限缓冲。若 B 的 TCP 已收到字节、而 B 的 IM 程序迟迟不 Read,缓冲里的未取数据会增加;接收端可以在确认中通告较小的可用窗口,极端时通告零窗口,让发送端暂时停止推进新数据,等待接收端再次通告空间。这是流量控制,目标是避免发送方把接收方内存填爆。零窗口不是“用户已退出登录”,也不是“B 已读到这里”;它只描述某一方向的接收容量状态。
纸上假设接收缓冲起初有 12 kB 可用空间,网关试图以 8 kB/s 到达,B 的应用只能以 2 kB/s 取走,且暂不考虑 TCP 已施加的减速和协议开销。净积压约为 8−2=6 kB/s;若速率保持不变,12/6=2 s 就会填满。真实 TCP 会因 rwnd 缩小而使到达速率变化,因此这个 2 s 只是“完全没有背压”的纸上填满时间,不是某台设备的实测结果。B 的应用后来读走数据、空位扩大,接收端再通告窗口更新,发送方才有条件继续发。
| 纸上时刻 | 若仍按原速率推进,累计净积压 | 对 rwnd 的直觉 |
|---|---|---|
| 初始 | 0 kB | 有 12 kB 空间 |
| 1 s | 6 kB | 可用空间减小,通告窗口可能收缩 |
| 2 s | 12 kB | 理想化模型已满,必须背压或暂停新字节 |
接收端窗口缩小能反向约束该 TCP 流,不代表网关出站消息队列已经安全有界:业务上游还可能不断把新消息塞进内存,等 socket 可写。后面必须设计应用层背压。若网关同时向许多 B 类慢设备扇出,单设备少量等待也会累积为显著的服务器内存占用。
三、拥塞窗口 cwnd:即使 B 读得快,路也可能塞车
另一种纸上情景:B 的应用读取很快,接收缓冲宽裕,rwnd 很大;但中间某条链路容量有限,多条连接同时竞争,网络设备排队、丢包或通过其他信号反映拥塞。发送方的 TCP 维护 cwnd,逐步探测允许的在途量,并在拥塞信号出现时收缩或调整。RFC 5681 描述了一类经典 TCP 拥塞控制行为;真实系统的具体算法和参数可能不同,本章只讲“保护路径、不能无界发送”的共同机制。
在一个忽略其他约束的入门模型里:
尚未确认的在途字节 ≤ min(接收端允许的 rwnd, 发送端允许的 cwnd)
可继续发送的新字节 ≈ min(rwnd, cwnd) − 已在途字节如果 rwnd=80 kB、cwnd=20 kB,窗口上界由网络侧的 cwnd 限制;若 rwnd=8 kB、cwnd=40 kB,由接收端的 rwnd 限制。真实 TCP 还受发送缓冲、当前 ACK、应用写入速率、其他协议行为影响,这个 min 是因果判断模型,不是用两个仪表盘数字直接精确预测吞吐的公式。
因此,吞吐变低不必然代表 B 读得慢;rwnd 充足而 RTT、重传或网络排队变化时,应怀疑路径因素。反过来,rwnd 缩小也不能由此宣布网络没有拥塞:两种约束可以同时存在。需要分层、同时间窗的证据,而不是从一条慢 Trace 或一次超时直接归因。
四、带宽时延积 BDP:为什么需要足够多的字节在路上
带宽时延积(BDP)用“可用速率 × 往返时间”估计在一个 RTT 里可占用的在途数据量。全章按十进制单位计算:1 MB=1000 kB,1 Byte=8 bit。设纸上路径容量 8 Mb/s = 1 MB/s、RTT 100 ms = 0.1 s:
BDP = 1 MB/s × 0.1 s = 0.1 MB = 100 kB如果有效在途窗口只有 10 kB,那么在每次 RTT 才释放同量窗口的简化模型里,吞吐上界大约 10 kB / 0.1 s = 100 kB/s = 0.8 Mb/s,远低于 8 Mb/s 的纸上路径容量。窗口接近 100 kB 时才有机会充分利用这条路径,前提还包括接收端能读、网络允许、发送方有数据且没有其他竞争/开销。BDP 是估算需要多少在途数据的量纲工具,不是“实际吞吐必定为 8 Mb/s”的测试结果。
| 项目 | 数值 | 单位检查 |
|---|---|---|
| 路径容量 | 8 Mb/s = 1 MB/s | 位/秒换成字节/秒需除以 8 |
| RTT | 100 ms = 0.1 s | 与速率中的秒对齐 |
| BDP | 100 kB | 速率乘时间得到数据量 |
| 10 kB 窗口的简化上界 | 0.8 Mb/s | 数据量除以 RTT 得速率 |
不能据此把每条 IM 消息做成 100 kB,也不能以调大 socket 缓冲来让离线 B 的设备“自动已送达”。大窗口只在慢点是本可用的在途量时有帮助;若接收端不读或路径拥塞,别的限制仍会压住发送。
五、缓冲可以藏住抖动,也可能制造尾延迟
队列能吸收短时突发,但如果持续到达速率高于排出速率,就会增长。假设瓶颈以 1 MB/s 排出,已有 200 kB 等待数据,且暂不考虑新到达与调度差异,一个排在队尾的数据至少要等大约 200 kB / 1000 kB/s = 0.2 s = 200 ms 才轮到服务;若队列已有 1 MB,相同纸上速率对应约 1 s。这是排队时延估计,不是 TCP ACK、应用延迟或真实 P99 的测量。
排队时间的第一近似 ≈ 前面等待的字节数 ÷ 瓶颈排出速率无限增加缓冲会让突发更不容易立刻丢包,却可能让 B 的少数消息在长队尾端等待很久。平均吞吐或少数成功样本看起来仍可接受,用户体感却在尾部变差;11.02 已说明 P99 不能凭一次慢请求估算,也不能拿分组 P99 直接平均。TCP 是有序字节流:若前段丢失,后段即使到达也要等缺口补齐后才能按序交给应用,这是另一种等待;它与应用自己的出站消息队列排队应分别标记。
网络队列是否因拥塞持续积压,需要看路径和竞争;应用缓冲是否积压,要看生产/消费速率。RFC 7567 的主动队列管理讨论为什么排队延迟需要控制。对本章教学 IM,最重要的工程结论不是“立刻配置某个内核算法”,而是先量出等待发生在哪一层,并为各层设有限容量与降级策略。
六、网关应用队列也要背压,TCP 窗口管不到所有消息
05.03 用容量 2 的 channel 讲过生产者、消费者与取消。现在把它放在 TCP 前面:群消息进入网关,网关为 B 准备出站消息;若 B 慢读,socket 写入可能变慢,出站任务处理速率下降,应用 queue 逐步满。TCP 的 rwnd/cwnd 只约束这条连接的字节发送,不会自动阻止上游从数据库、队列或群扇出任务继续产生对象。
| 应用队列满时的纸上策略 | 好处 | 业务代价/前提 |
|---|---|---|
| 阻塞/反压上游 | 不再无限吃内存 | 可能拖慢其他会话或生产者,需取消和隔离 |
| 拒绝新的实时投递 | 给出可见容量边界 | 不能把拒绝当 B 已收;需后续恢复路径 |
| 丢弃非关键提示 | 保留关键资源 | 只适合业务合同允许丢弃的事件 |
| 关闭慢连接 | 释放当前连接资源 | 需要重新登录/补拉历史的可靠来源 |
当前 S3 课程还没有实现完整的离线补拉与“至少一次投递”保证。不能在纸上写“队列满就丢消息,反正历史能补”并默认数据库已提交、客户端能从正确游标恢复。S5 会单独定义权威消息存储、重试身份、设备游标与补拉合同。在此之前,本章只要求:容量有限、拒绝或丢弃条件明确、上游能观察到背压,用户不被假成功误导。
七、诊断慢设备和拥塞:看同一时窗的不同位置
11.01 教先定义动作、时间窗、分母和确认点,11.03 教用日志/指标/Trace 留有限证据。对本章两个症状,纸上证据计划可这样写:
| 可疑现象 | 先看哪些候选证据 | 仍不能只凭一项下结论 |
|---|---|---|
| B 设备长期慢读 | 接收窗口趋势、设备应用读取速率、网关该连接写等待、应用队列深度 | rwnd 偶尔小一次不证明用户离线 |
| 路径拥塞 | 同时间窗 RTT/排队变化、重传/丢失信号、发送侧 cwnd 趋势、其他连接影响 | 一次重传也可能是 ACK 延迟或其他原因 |
| 两者混合 | 两组证据同时出现,分别列阶段与顺序 | 只看单条 Trace 不能估总体占比 |
如果 rwnd 充足、B 程序读取正常,却观察到路径 RTT 和重传持续变化,才有理由进一步调查拥塞;如果网络 RTT 稳定但 B 的读取任务停止、接收缓冲持续占满,则要先查设备应用。两者只是假设驱动的方向,没有实测数据就不能报告“根因已经确认”。应再设计独立复现或控制变量的个人实验,记录设备、路径、窗口、负载和错误;本章没有运行这些实验。
把“消息到 B 的网络连接”与“B 用户真正看见消息”分开。TCP 接收窗口和 ACK 只能说明字节流状态,应用队列指标只能说明网关内部等待,设备处理/已读需要更高层确认。这个边界决定优化对象:盲目增大 TCP 缓冲可能使网络图更平滑,却让 IM 的尾部体验更差。
八、交付两份瓶颈推演与分层练习
交付一份慢设备时间线(12 kB 空间、8/2 kB/s 生产/消费),一份网络路径时间线(8 Mb/s、100 ms RTT、10/100 kB 有效窗口),再写 200 kB 排队对应的纸上额外等待。为网关容量 2 的应用队列选择一个有限策略,标明消息是否已受理/持久、是否能补拉、是否应通知 A 结果未知。不得把这些数字报告成真实 OpenIM 或本项目性能。
分层练习:先答,再展开反馈
1. `rwnd` 主要保护谁?
接收端的有限接收缓冲。
2. `cwnd` 主要反映谁对路径的限制?
发送端 TCP 的拥塞控制对网络在途量的限制。
3. `rwnd=8 kB`、`cwnd=40 kB`,概念窗口由谁限制?
接收端 rwnd;还要扣除已在途字节等实际条件。
4. `rwnd=80 kB`、`cwnd=20 kB`,概念窗口由谁限制?
发送侧 cwnd 的路径约束。
5. B 程序不 Read,接收缓冲可能怎样?
逐渐占满,接收端通告的可用窗口可能变小甚至为零。
6. 零窗口可证明 B 已退出账号吗?
不能,只表示该 TCP 方向的接收空间状态。
7. 8 kB/s 到达、2 kB/s 消费,纸上净积压多少?
6 kB/s。
8. 忽略 TCP 背压,12 kB 空间约多久填满?
12/6=2 s;真实到达速率会随窗口变化。
9. B 读得快而网关写慢,一定是 B 的错吗?
不一定,网络拥塞和其他阶段也可能限制发送。
10. `min(rwnd,cwnd)` 是实测吞吐公式吗?
不是,是纸上的在途约束模型;还受缓冲、ACK、应用速率和开销影响。
11. 8 Mb/s 按十进制约等于多少 MB/s?
1 MB/s。
12. 100 ms 等于多少秒?
0.1 s。
13. 1 MB/s×0.1 s 的 BDP 是多少?
0.1 MB,即十进制 100 kB。
14. 10 kB 有效窗口、RTT 0.1 s 的简化吞吐上界是多少?
100 kB/s,即 0.8 Mb/s,忽略开销和其他瓶颈。
15. BDP=100 kB 意味每条 IM 消息必须 100 kB 吗?
不意味着;它估计在途数据量,不是应用消息大小。
16. 1 MB/s 瓶颈前排 200 kB,纸上额外等待约多少?
200/1000=0.2 s=200 ms,实际还受新到达和调度影响。
17. 缓冲从 200 kB 增到 1 MB,一定改善 B 的尾延迟吗?
不一定;按同一排出速率,排队时间可能从约 200 ms 增到约 1 s。
18. TCP 接收窗口缩小会自动让网关所有业务队列有界吗?
不会。上游仍可能继续产生消息,应用层需单独背压。
19. 网关容量 2 队列已满,能无条件丢弃聊天正文吗?
不能。要先定义消息是否权威保存、失败反馈和补拉/重试合同。
20. 只看一次重传可直接断言网络拥塞吗?
不能,需同时间窗的多项证据和进一步验证。
21. TCP ACK 能证明 B 已在界面展示 m-a 吗?
不能。TCP 字节确认与设备展示、已读不同。
22. 同时慢设备和拥塞时该怎样分析?
分别列接收窗口/读取速率与路径 RTT/丢失/拥塞证据,按阶段和时间窗判断。
来源与下一步
- RFC 9293:TCP:接收窗口与字节流的流量控制基础。
- RFC 5681:TCP 拥塞控制:
cwnd与路径拥塞控制的经典机制;具体部署算法需另核对。 - RFC 6349:吞吐测试框架:BDP 与窗口/吞吐的单位关系。
- RFC 7567:主动队列管理:排队延迟与缓冲取舍。
- Go
net包:以后个人网络 I/O 实践的缓冲入口,本章没有运行连接或基准。
按学习路线,下一章04.07 TLS 与身份从握手、证书与名称校验补上安全传输身份;随后才进入 09.12 的完整服务项目课程。离开本章前,应能解释谁在减速、哪层缓冲增长、单位怎样换算、TCP 限制为何不能代替 IM 业务背压。