1.写在前面
上一篇博客已经介绍了TCP协议的内容的一部分了,今天咱们继续介绍剩下的部分。
2.操作系统缓冲区与滑动窗口的关系
窗口与缓存
应用层没有及时读取缓存
收缩窗口导致的丢包
- 先收缩窗口,再减少缓存
- 窗口关闭后,定时探测窗口大小
飞行中报文的适合数量
- bps*RTT
Linux下调整接收窗口与应用缓存
Linux中对TCP缓冲区的调整方式
- net.ipv4.tcp_rmem = 4096 87380 6291456
- 读缓存最小值、默认值、最大值,单位字节,覆盖 net.core.rmem_max
- net.ipv4.tcp_wmem = 4096 16384 4194304
- 写缓存最小值、默认值、最大值,单位字节,覆盖net.core.wmem_max
- net.ipv4.tcp_mem = 1541646 2055528 3083292
- 系统无内存压力、启动压力模式阀值、最大值,单位为页的数量
- net.ipv4.tcp_moderate_rcvbuf = 1
3.如何减少小报文提高网络效率?
SWS(Silly Window syndrome)糊涂窗口综合症
- 小窗口通告
SWS 避免算法
- 接收方
- David D Clark 算法:窗口边界移动值小于 min(MSS, 缓存/2)时,通知窗口为 0
- 发送方
- Nagle 算法:TCP_NODELAY 用于关闭 Nagle 算法
- 没有已发送未确认报文段时,立刻发送数据
- 存在未确认报文段时,直到:1-没有已发送未确认报文段,或者 2-数据长度达到 MSS 时再发送
TCP delayed acknowledgment 延迟确认
-
当有响应数据要发送时,ack 会随着响应数据立即发送给对方 -
如果没有响应数据,ack 的发 送将会有一个延迟,以等待看是否有响应数据可以一起发送 -
如果在等待发送 ack 期间,对方的第二个数据段又到达了,这时要立即发送 ack -
-
Nagle VS delayed ACK
- 关闭 delayed ACK:TCP_QUICKACK
- 关闭 Nagle:TCP_NODELAY
Linux 上更为激进的”Nagle”:TCP_CORK
4.拥塞控制:慢启动
全局思考:拥塞控制
- 慢启动
- 拥塞避免
- 快速重传
- 快速恢复
拥塞控制历史
- 以丢包作为依据
- New Reno:RFC6582
- BIC:Linux2.6.8 – 2.6.18
- CUBIC(RFC8312):Linux2.6.19
- 以探测带宽作为依据
慢启动
- 拥塞窗口cwnd(congestion window)
- 通告窗口rwnd(receiver‘s advertised window)
- 发送窗口swnd = min(cwnd,rwnd)
- 每收到一个ACK,cwnd扩充一倍
慢启动的初始窗口
- 慢启动初始窗口 IW(Initial Window)的变迁
- 1 SMSS:RFC2001(1997)
- 2 - 4 SMSS:RFC2414(1998)
- IW = min (4SMSS, max (2SMSS, 4380bytes))
- 10 SMSS:RFC6928(2013)
- IW = min (10MSS, max (2MSS, 14600))
5.拥塞控制:拥塞避免
拥塞避免
- 慢启动阈值 ssthresh(slow start threshold)
- 达到 ssthresh 后,以线性方式增加 cwnd cwnd += SMSS*SMSS/cwnd
慢启动与拥塞控制
6.拥塞控制:快速重传与快速恢复
为何会接收到一个失序数据段?
- 若报文丢失,将会产生连续的失序 ACK 段
- 若网络路径与设备导致数据段失序,将会产生少量的失序 ACK 段
- 若报文重复,将会产生少量的失序 ACK 段
快速重传(RFC2581)
- 接收方
- 当接收到一个失序数据段时,立刻发送它所期待的缺口 ACK 序列号
- 当接收到填充失序缺口的数据段时,立刻发送它所期待的下一个 ACK 序列号
- 发送方
- 当接收到 3 个重复的失序 ACK 段(4 个相同的失序 ACK 段)时,不再等待重传定时器的触发,立刻基于快速重传机制重发报文段
超时不会启动快速重传
快速重传下一定要进入慢启动吗?
- 收到重复 ACK,意味着网络仍在流动
- 慢启动会突然减少数据流
快速恢复(RFC2581)
- 启动快速重传且正常未失序 ACK 段到达前,启动快速恢复
- 每收到一个重复 ACK,cwnd 增加 1个 MSS
- 当新数据 ACK 到达后,设置 cwnd为 ssthresh
7.SACK 与选择性重传算法
仅重传丢失段保守乐观
- 累积确认 Sequence 序号的问题
- Client 无法告知收到了 Part4
- Server 发送窗口/Client 接收窗口停止
重传所有段–积极悲观
重传所有段:积极悲观
仅重传丢失段:保守乐观
- 大量丢包时效率低下
SACK:TCP Selective Acknowledgment
- RFC2018
引入SACK
- 选择性确认
SACK
- Left Edge of Block
- Right Edge of Block
8.从丢包到测量驱动的拥塞控制算法
飞行中的数据与确认报文
大管道向小管道传输数据引发拥堵
最佳控制点在哪?
- 基于丢包的拥塞控制点
- 最佳控制点
- RTT 与 Bw 独立变化
- 同时只有一个可以被准确测量
空队列的效果最好!
BBR:TCP Bottleneck Bandwidth and Round-trip propagation time
- 由 Google 于 2016 发布,Linux4.9 内核引入,QUIC 使用
9.Google BBR 拥塞控制算法原理
BBR 在 Youtube 上的应用:吞吐量提升
BBR 在 Youtube 上的应用:RTT 时延变短
BBR 在 Youtube 上的应用:重新缓冲时间间隔变长
最佳控制点在哪?
- 基于丢包的拥塞控制算法
- 左边纵线(对整体网络有效)
- RTprop 与 BtlBw 独立变化
- 同时只有一个可以被准确测量
BBR 如何找到准确的 RTprop 和 BtlBw?
RTT 里有排队噪声
什么是 RTprop?是物理属性
基于 pacing_gain 调整
- 700 ms内的测量
- 如何检测带宽变大?
- 定期提升pacing_gain
当线路变换时 pacing_gain 的作用
- 20 秒:10-Mbps, 40-ms 升至 20 Mbps
- 40 秒:又降至 10-Mbps
对比 CUBIC 下的慢启动
- 10-Mbps, 40-ms
- 慢启动
- startup
- drain
- probe BW
多条初始速度不同的 TCP 链路快速的平均分享带宽
- 100-Mbps/10-ms
Google B4 WAN实践
- 2-25 倍吞吐量提升
- 75%连接受限于 linux kerner 接收缓存
- 在美国-欧洲路径上提升 linux kernal 接收缓存上限后有 133倍提升
RTT 大幅下降
- 10-Mbps, 40-ms
不同丢包率下的吞吐量:CUBIC VS BBR
- 100-Mbps/100-ms
- 红色 CUBIC
- 绿色 BBR
Youtube 一周以上 2 亿次播放数据统计
SGSN 移动网络
- 128-Kbps/40-ms
- 新连接建立困难
收到 Ack 时
更新 RTprop 、BtlBw
当发送数据时
10.四次握手关闭连接
关闭连接:防止数据丢失;与应用层交互
- FIN:结束
- ACK:确认
两端同时关闭连接
TCP 状态机
11 种状态
- CLOSED
- LISTEN
- SYN-SENT
- SYN-RECEIVED
- ESTABLISHED
- CLOSE-WAIT
- LAST-ACK
- FIN-WAIT1
- FIN-WAIT2
- CLOSING
- TIME-WAIT
3 种事件
- SYN
- FIN
- ACK
11.优化关闭连接时的TIME-WAIT状态
TIME-WAIT状态过短或者不存在会怎么样?
- MSL(Maximum Segment Lifetime)
- 维持 2MSL 时长的 TIME-WAIT 状态
- 保证至少一次报文的往返时间内端口是不可复用
linux下TIME_WAIT优化:tcp_tw_reuse
- net.ipv4.tcp_tw_reuse = 1
- 开启后,作为客户端时新连接可以使用仍然处于 TIME-WAIT 状态的端口
- 由于 timestamp 的存在,操作系统可以拒绝迟到的报文
- net.ipv4.tcp_timestamps = 1
TIME_WAIT 优化
- net.ipv4.tcp_tw_recycle = 0
- 开启后,同时作为客户端和服务器都可以使用 TIME-WAIT 状态的端口
- 不安全,无法避免报文延迟、重复等给新连接造成混乱
- net.ipv4.tcp_max_tw_buckets = 262144
- time_wait 状态连接的最大数量
- 超出后直接关闭连接
RST 复位报文
12.keepalive 、校验和及带外数据
TCP 的 Keep-Alive 功能
- Linux 的 tcp keepalive
- 发送心跳周期
- Linux: net.ipv4.tcp_keepalive_time = 7200
- 探测包发送间隔
- net.ipv4.tcp_keepalive_intvl = 75
- 探测包重试次数
- net.ipv4.tcp_keepalive_probes = 9
违反分层原则的校验和
- 对关键头部数据(12字节)+TCP 数据执行校验和计算
- 计算中假定 checksum 为0
应用调整 TCP 发送数据的时机
紧急处理数据
13.面向字节流的 TCP 连接如何多路复用?
Multiplexing 多路复用
- 在一个信道上传输多路信号或数据流的过程和技术
HTTP2:TCP 连接之上的多路复用
非阻塞 socket:同时处理多个 TCP 连接
epoll+非阻塞 socket
- epoll 出现:linux 2.5.44
- 进程内同时刻找到缓冲区或者连接状态变化的所有 TCP 连接
- 3 个 API
- epoll_create
- epoll_ctl
- epoll_wait
epoll 为什么高效?
- 活跃连接只在总连接的一小部分
非阻塞+epoll+同步编程 = 协程
14.四层负载均衡可以做什么?
OSI 模型下的七层 LB 与四层 LB
四层负载均衡与表示层的 TLS 卸载
四层负载均衡与连接五元组
三层路由器与四层负载均衡
多层 LB
- 对外 LB
- 内部 LB
信任的边界
UDP 负载均衡的理论依据
15.写在最后
本篇博客主要介绍了TCP协议剩下的内容,剩下的还有一个网络协议中IP协议。
|