diva-notes
  • README
  • Ads
    • 定价策略
    • 广告层级
    • 归因模型
    • 买量
    • Chat GPT
    • Google
  • AI
    • 参考资料
    • Chat GPT
    • stable-diffusion-webui安装
  • Algorithm
    • 倍增
    • 并查集
    • 参考
    • 环的判断
    • 凸包
    • 蓄水池抽样
    • 最短路径
    • 最小生成树
    • KMP算法
    • Rabin-Karp算法
    • Tarjan桥算法
  • Architecture
    • Serverless
  • Career
  • CICD
    • 代码质量
    • CICD实践
  • Data Structure
    • 布谷鸟过滤器
    • 布隆过滤器
    • 浮点
    • 红黑树
    • 锁
    • LSM树
  • DB
    • My SQL
      • 隔离级别
      • 架构
      • 索引
      • 锁
      • 页结构
      • 主从同步
      • ACID
      • Log
      • MVCC
      • Questions
    • Postgres
      • 持久化
      • 对比MySQL
      • 隔离级别
      • 索引
      • Greenpulm
      • MVCC
    • 倒排索引
    • 列式存储
    • H Base
    • HDFS
    • MPP数据库选型
    • Questions
  • Distributed System
    • 分布式事务
    • 服务网格
    • BASE理论
    • CAP
    • Etcd
    • Raft协议
    • ZAB协议
  • Go
    • 1.语言基础
      • 1.CPU寄存器
      • 2-1.函数调用
      • 2-2.函数调用栈
      • 2.接口
      • 3.汇编
      • 4.调试
    • 2.编译
      • 1.编译
      • 2.词法与语法分析
      • 3.类型检查
      • 4.中间代码生成
      • 5.机器码生成
    • 3.数据结构
      • 1.数组array
      • 2.切片slice
      • 3.哈希表map
      • 4.字符串
    • 4.常用关键字
      • 1.循环
      • 2.defer
      • 3.panic和recover
      • 4.make和new
    • 5.并发编程
      • 1.上下文Context的实现
      • 2-1.runtime.sema信号量
      • 2-2.sync.Mutex的实现
      • 2-3.sync.WaitGroup
      • 2-4.sync.Once的实现
      • 2-5.sync.Map的实现
      • 2-6.sync.Cond
      • 2-7.sync.Pool的实现
      • 2-8.sync.Semaphore的实现
      • 2-9.sync.ErrGroup
      • 3.定时器Timer的实现
      • 4.Channel的实现
      • 5-1.调度-线程
      • 5-2.调度-MPG
      • 5-3.调度-程序及调度启动
      • 5-4.调度-调度策略
      • 5-5.调度-抢占
      • 6.netpoll实现
      • 7.atomic
    • 6.内存管理
      • 1-1.内存分配基础-TCmalloc
      • 1-2.内存分配
      • 2.垃圾回收
      • 3.栈内存管理
    • 参考
    • 各版本特性
    • 坑
    • Go程序性能优化
    • http.Client
    • net.http路由
    • profile采样的实现
    • Questions
    • time的设计
  • Kafka
    • 高可用
    • 架构
    • 消息队列选型
    • ISR
    • Questions
  • Network
    • ARP
    • DNS
    • DPVS
    • GET和POST
    • HTTP 2
    • HTTP 3
    • HTTPS
    • LVS的转发模式
    • NAT
    • Nginx
    • OSI七层模型
    • Protobuf
    • Questions
    • REST Ful
    • RPC
    • socket缓冲区
    • socket详解
    • TCP滑动窗口
    • TCP连接建立源码
    • TCP连接四元组
    • TCP三次握手
    • TCP数据结构
    • TCP四次挥手
    • TCP拥塞控制
    • TCP重传机制
    • UDP
  • OS
    • 磁盘IO
    • 调度
    • 进程VS线程
    • 零拷贝
    • 内存-虚拟内存
    • 内存分配
    • 用户态VS内核态
    • 中断
    • COW写时复制
    • IO多路复用
    • Questions
  • Redis
    • 安装
    • 参考
    • 高可用-持久化
    • 高可用-主从同步
    • 高可用-Cluster
    • 高可用-Sentinel
    • 缓存一致性
    • 事务
    • 数据结构-SDS
    • 数据结构-Skiplist
    • 数据结构-Ziplist
    • 数据结构
    • 数据类型-Hashtable
    • 数据类型-List
    • 数据类型-Set
    • 数据类型-Zset
    • 数据淘汰机制
    • 通信协议-RESP
    • Questions
    • Redis6.0多线程
    • Redis分布式锁
    • Redis分片
  • System Design
    • 本地缓存
    • 错误处理
    • 大文件处理
    • 点赞收藏关注
    • 短链接生成系统
    • 负载均衡
    • 高并发高可用
    • 规则引擎
    • 集卡活动
    • 秒杀系统
    • 评论系统
    • 熔断
    • 限流
    • 延迟队列
    • Docker
    • ES
    • K 8 S
    • Node.js
    • Questions
  • Work
    • Bash
    • Charles
    • Code Review
    • Ffmpeg
    • Git
    • intellij插件
    • I Term 2
    • Mac
    • mysql命令
    • Nginx
    • postgresql命令
    • Protoc
    • Ssh
    • Systemd
    • Tcp相关命令
    • Vim
Powered by GitBook
On this page
  • 慢热启动算法 – Slow Start
  • 拥塞避免算法 – Congestion Avoidance
  • 拥塞状态时的算法
  1. Network

TCP拥塞控制

PreviousTCP四次挥手NextTCP重传机制

Last updated 2 years ago

如果网络上的延时突然增加,那么,TCP 对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,进入恶性循环被不断地放大。 如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成网络风暴,TCP 这个协议就会拖垮整个网络。

所以,TCP 不能忽略网络上发生的事情,而无脑地一个劲地重发数据,对网络造成更大的伤害。对此 TCP 的设计理念是:TCP 不是一个自私的协议,当拥塞发生的时候,要做自我牺牲,类似于熔断的概念。就像交通阻塞一样,每个车都应该把路让出来,不要再去抢路了。

关于拥塞控制的论文请参看《》(PDF)

拥塞控制主要是四个算法:1. 慢启动,2. 拥塞避免,3. 拥塞发生,4. 快速恢复。这四个算法不是一天都搞出来的,这个四算法的发展经历了很多时间,到今天都还在优化中。

  1. 慢启动:刚加入网络的连接,滑动窗口较小。每过一个 RTT,窗口大小翻倍

  2. 拥塞避免:窗口到达阈值后,每过一个 RTT,大小只+1

  3. 拥塞处理:发生超时时,阈值设为窗口大小的一般,窗口重置为1,重新开始慢启动

慢热启动算法 – Slow Start

慢启动的意思是,刚刚加入网络的连接,以一个较低的速度开始传输,一点一点地提速。

慢启动的算法如下 (cwnd 全称 Congestion Window,拥塞窗口,表示可以并行发送的包的窗口大小):

  1. 连接建好时先初始化 cwnd = 1,表明可以传一个 MSS 大小的数据。

  2. 每当收到一个 ACK,cwnd++;呈线性上升

  3. 每当过了一个 RTT,cwnd = cwnd*2;呈指数上升

  4. 还有一个慢启动阈值 ssthresh(slow start threshold),当 cwnd >= ssthresh 时,就会进入 "拥塞避免算法"

如果网速很快的话,RTT 会短,那么,这个慢启动就一点也不慢,新加入的连接很快就能到达峰速:

Linux 2.6 下,cwnd 是跟 MSS 的值来变的,如果 MSS< 1095,则 cwnd = 4;如果 MSS>2190,则 cwnd=2;其它情况下,则是 3

Linux 3.0 下,cwnd 初始值为 10

拥塞避免算法 – Congestion Avoidance

前面说过,还有一个 ssthresh (slow start threshold),是一个上限,当 cwnd >= ssthresh 时,就会进入 "拥塞避免算法"。一般来说 ssthresh 的值是 65535,单位是字节,当 cwnd 达到这个阈值后,算法如下:

  1. 收到一个 ACK 时,cwnd = cwnd + 1/cwnd

  2. 当每过一个 RTT 时,cwnd = cwnd + 1

这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。很明显,是一个线性上升的算法。

拥塞状态时的算法

前面我们说过,当丢包的时候,会有两种情况:

  1. 等到 RTO 超时,重传数据包。TCP 认为这种情况太糟糕,反应也很强烈。

    1. sshthresh = cwnd /2

    2. cwnd 重置为 1

    3. 进入慢启动过程

  2. 快速重传算法,也就是在收到3个 duplicate ACK 时就开启重传,而不用等到 RTO 超时。

    1. TCP Tahoe 的实现和 RTO 超时一样。

    2. TCP Reno 的实现是:

      1. sshthresh = cwnd / 2

      2. cwnd = sshthresh + 3 * MSS

      3. 进入快速重传算法 Fast Recovery

我们可以看到 RTO 超时后,sshthresh 会变成 cwnd 的一半。这意味着,如果是 cwnd <= sshthresh 时出现的丢包,那么 TCP 的 sshthresh 就会减掉一半,然后等 cwnd 又很快地以指数级增涨爬到这个地方时,又会慢慢的线性增涨。可以看到,TCP 是怎么通过这种强烈地震荡快速而小心得找到网站流量的平衡点的。

参考

陈皓 - TCP 的那些事儿(上)
Congestion Avoidance and Control
img
这里写图片描述