分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
台风海马来临前的两个几乎通宵的夜晚,我用一篇关于BBR算法的文章的迎接海马!公司在昨晚响应深圳市停工,停课号召,发布了在家办公(请注意,不是放假...)通知...其实吧,我觉得停电才是王道,你觉得呢?
在前一篇关于bbr算法的文章《 来自Google的TCP BBR拥塞控制算法解析》(这可能是第一篇中文版的bbr算法相关的文章)中,我简述了bbr算法的框架,算是大致介绍了。本文中,我想深入bbr算法pipe状态机的一些细节,但是我不会继续使用”状态机“这样的术语,我选择使用变速引擎这样的说法,来展示一个现代高速的TCP变速引擎是如何为数据传输提供强劲动力的。
这组引擎完全从bbr算法中抽象生成,想法来自于我们奔跑或者开车的过程,突然发现,bbr算法的思想精髓简直就和我们在人多的跑道上奔跑以及在高速公路上开车时的思路完全一致啊!
我不禁感叹万物的统一并诅咒虚无,在胃里灼烧感正嗨的时候,完成了本文!
就要开始了!
1).反馈性差
以Reno为例,TCP发送端在拥塞避免阶段收到ACK后,无条件地将cwnd增加1/cwnd,在慢启动阶段收到ACK后cwnd增加1,这是毫无根据的,然而Reno并没有什么更好的做法,只能瞎猜!后来的Westwood,Vegas,BIC等算法,相对Reno/NewReno更加智能了一步,但还是傻瓜!再往后,CUBIC搞了一个高大上的以三次方程凸凹曲线来抉择的增窗机制,看似十分地“博士”,并且十分地“经理”,然而还是无法高效利用互联网的空闲带宽,相反在碰到异常现象,比如丢包,拥塞的时候,反应太过保守,在保守的路线上趋于激烈,即激烈地保守降低拥塞窗口,更加可悲的是,这个窗口下降的过程并不受这些算法所控制。
2).拥塞算法被接管
在TCP拥塞控制机制发现丢包时(即RTO或者N次重复的ACK等),TCP会完全接管拥塞控制算法,自己控制拥塞窗口。然而问题是,这种所谓的丢包可能并不是真的丢包,这只是TCP认为丢包而已,这是30年前的丢包判断机制了...真的丢包了吗?不一定啊!然而只要TCP认为丢包,就会接管拥塞控制算法(起码在Linux上是这样...)。这使我不得开心颜!我曾经修改过Linux TCP的PRR逻辑,只求降窗过程不那么猛而已...Linux TCP为了这个降窗也是费尽心思,先后经历了多种方案,比如 Halving Rate, PRR等,唉,干嘛不直接都交给拥塞控制算法呢??
是否进入tcp_cwnd_reduction的异常模式,是由下面的逻辑来判断的:
这个会让TCP拥塞模块怎么想?!除了抛出一个ssthresh之外对异常的处理无能为力,事实上这根本与它无关!
都改了什么呢?我们看一下核心函数tcp_cong_control就知道了(我这里不谈2.6内核以及3.x内核中没有抽离cong_control的版本):
在前一篇关于bbr算法的文章《 来自Google的TCP BBR拥塞控制算法解析》(这可能是第一篇中文版的bbr算法相关的文章)中,我简述了bbr算法的框架,算是大致介绍了。本文中,我想深入bbr算法pipe状态机的一些细节,但是我不会继续使用”状态机“这样的术语,我选择使用变速引擎这样的说法,来展示一个现代高速的TCP变速引擎是如何为数据传输提供强劲动力的。
这组引擎完全从bbr算法中抽象生成,想法来自于我们奔跑或者开车的过程,突然发现,bbr算法的思想精髓简直就和我们在人多的跑道上奔跑以及在高速公路上开车时的思路完全一致啊!
我不禁感叹万物的统一并诅咒虚无,在胃里灼烧感正嗨的时候,完成了本文!
就要开始了!
1.Linux TCP迄今为止的拥塞控制机制
我并不了解其它平台的TCP拥塞控制算法实现,但是我了解Linux的,迄今为止,在bbr刚刚被引入之后,Linux的拥塞控制算法分为两类:保守模式
bbr之前以Reno为基础,包括Reno,NewReno,...原理几乎都不变,这些算法有两个特点:1).反馈性差
以Reno为例,TCP发送端在拥塞避免阶段收到ACK后,无条件地将cwnd增加1/cwnd,在慢启动阶段收到ACK后cwnd增加1,这是毫无根据的,然而Reno并没有什么更好的做法,只能瞎猜!后来的Westwood,Vegas,BIC等算法,相对Reno/NewReno更加智能了一步,但还是傻瓜!再往后,CUBIC搞了一个高大上的以三次方程凸凹曲线来抉择的增窗机制,看似十分地“博士”,并且十分地“经理”,然而还是无法高效利用互联网的空闲带宽,相反在碰到异常现象,比如丢包,拥塞的时候,反应太过保守,在保守的路线上趋于激烈,即激烈地保守降低拥塞窗口,更加可悲的是,这个窗口下降的过程并不受这些算法所控制。
2).拥塞算法被接管
在TCP拥塞控制机制发现丢包时(即RTO或者N次重复的ACK等),TCP会完全接管拥塞控制算法,自己控制拥塞窗口。然而问题是,这种所谓的丢包可能并不是真的丢包,这只是TCP认为丢包而已,这是30年前的丢包判断机制了...真的丢包了吗?不一定啊!然而只要TCP认为丢包,就会接管拥塞控制算法(起码在Linux上是这样...)。这使我不得开心颜!我曾经修改过Linux TCP的PRR逻辑,只求降窗过程不那么猛而已...Linux TCP为了这个降窗也是费尽心思,先后经历了多种方案,比如 Halving Rate, PRR等,唉,干嘛不直接都交给拥塞控制算法呢??
总的来讲,bbr之前的拥塞控制逻辑在执行过程中会分为两种阶段,即正常阶段和异常阶段。在正常阶段中,TCP模块化的拥塞控制算法主导窗口的调整,在异常阶段中,TCP核心的拥塞控制状态机从拥塞控制算法那里接管窗口的计算,在Linux的实现中,这是由以下逻辑表示的:
static void tcp_cong_control(struct sock *sk, u32 ack, u32 acked_sacked, int flag){ if (tcp_in_cwnd_reduction(sk)) { // 异常模式 /* Reduce cwnd if state mandates */ // 在进入窗口下降逻辑之前,还需要tcp_fastretrans_alert来搜集异常信息并处理异常过程。 tcp_cwnd_reduction(sk, acked_sacked, flag); } else if (tcp_may_raise_cwnd(sk, flag)) { // 正常模式或者安全的异常模式! /* Advance cwnd if state allows */ tcp_cong_avoid(sk, ack, acked_sacked); } tcp_update_pacing_rate(sk);}
是否进入tcp_cwnd_reduction的异常模式,是由下面的逻辑来判断的:
if (tcp_ack_is_dubious(sk, flag)) { is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); tcp_fastretrans_alert(sk, acked, is_dupack, &flag, &rexmit);}
这个会让TCP拥塞模块怎么想?!除了抛出一个ssthresh之外对异常的处理无能为力,事实上这根本与它无关!
全速模式
bbr之后以bbr为基础的算法,其核心并不是bbr本身,而是bbr算法为了运行对Linux TCP框架的修改!bbr并不是最终的算法,更不是神话,它只是个开始,它把TCP的tcp_ack完全改了,改了之后,如果你有什么好的想法,便可以自由发挥了!都改了什么呢?我们看一下核心函数tcp_cong_control就知道了(我这里不谈2.6内核以及3.x内核中没有抽离cong_control的版本):
static void tcp_cong_control(struct sock *sk, u32 ack, u32 acked_sacked, int flag, const struct rate_sample *rs){ const struct inet_connection_sock *icsk = inet_csk(sk); // 这里是新逻辑,如果回调中宣称自己有能力解决任何拥塞问题,那么交给它!