基于统计复用的分组交换网络拥塞控制的科普解释

来源:互联网 发布:讨厌大野智 知乎 编辑:程序博客网 时间:2024/04/28 11:13
最近收到很多邮件咨询各种问题,一般而言我能回答的就都回答了,我自有自知之明,绝不是什么大牛,然而也并不是菜鸟,所以说不管什么问题,我不一定能完美回答,但却也不是一点都不懂,因此我会尝试着去作答。
        由于最近写了几篇关于TCP拥塞控制的文章,就有人咨询我关于NCL,New Vegas,BBR等相关的问题,其实我知道他们的目的,不外乎两种原因,要么是自己想学习一下原理但可能遇到了看不懂的地方,前来询问,要么就是想自私的加速自己的TCP连接。对于前者,我非常乐意一起探讨,但对于后者,我只能回答“我也不知道”。其实,事实上我真的不知道如何给TCP加速,我唯一知道的就是,老老实实遵循现有的TCP逻辑,毕竟它们已经经过了各种环境的测试并被认为是合理的。对于如何去抢别人的带宽,我对这件事是非常非常反感的。因此我打算利用几乎一个通宵写下本文,意在告诉大家拥塞到底是怎么发生的,以及为什么拥塞是必然发生的,如果你真的理解了,你也就想通了为什么不要去抢别人的带宽,因为你做不到。
        本文比较长,但是却比较轻松,科普性质的,没有任何理论基础的人都应该可以看懂,中间加了分割线作为休息和思考的界限。我先从微信朋友圈刷屏开始。

刷屏 & BufferBloat the fucking

网络拥塞的原因,其实很简单。
        为什么网络会拥塞,答案其实是一个很简单的常识。我再一次以身试法站在一个殉道者的立场上来解释为什么网络会拥塞。我会告诉你们,在另一个网络,制造网络拥塞的那个人,就是我!
        然后你们就会理解到底什么是Buffer Bloat,最终你们会理解本文下面的部分以及BBR算法的核心理念。
        我不再用交通拥堵来解释网络拥塞,因为首先大家都这么解释,其次很多人对此早已麻木,毕竟就算堵在路上,不是还可以刷朋友圈逛淘宝么??所以,我尝试用微信朋友圈来解释网络拥塞,如果你想理解的更深刻,请加我为好友并且在彻底理解Buffer Bloat之前,不要屏蔽我,等你彻底理解了,删除我,删除之前,记得给个红包,5元即可!好吧,让我们上路。
        如今大家都玩微信和微博,特别是微信。玩微信的几乎都有刷朋友圈的习惯。你们碰到过有人刷屏吗?肯定碰到过!你们讨厌吗?肯定早就把刷屏者屏蔽了。为了理解什么是Buffer Bloat并且基于此理解网络拥塞的本质,请暂时不要屏蔽这些人,如果你们觉得还想理解的更加深入些,请加上我。
        把你们的大脑看作是一种处理信息的资源,微信朋友圈里的内容则是资源的一种。请问,你每天花多长时间刷朋友圈呢?每次多久呢?好吧,我暂且估计是每次10分钟。这10分钟,你能看到多少内容,你又想看到什么内容呢?你希望的朋友圈是这样的:
朋友1:
我昨天晚上挨了一顿打!...
朋友2:
我女朋友跟我分手了...
朋友3:
我把工作辞掉了,无所谓了...
朋友4:
周五我请看电影,想一起的请点个赞!...
朋友5:
人,要学会忍受孤独,因为你的孤独与他人无关【转载的鸡汤文】
朋友6:
年末有好礼,你来我就送!【卖东西的广告】
....

不可否认,这里面有你不喜欢的内容,比如那个鸡汤可能是你妈转的,虽然不喜欢也还是要点个赞什么的,卖东西的是你朋友或者上司不能得罪...然而,你之所以会花时间浪费你的大脑资源来刷朋友圈,还是希望得到一些你想看的东西的,你非常想看到朋友的八卦新闻,失恋离职之类的,隐约中其实在你内心也希望看到别人发一个生病的消息,然后回复一句无所谓的表现存在感的安慰,当然,你还希望可以从朋友圈信息中得到利益,比如有人请客什么的。
        对于发这些信息的人,他们渴望什么呢?既然发出去,就是希望有人看有人关注,不管什么目的,根本原因就是希望有人看!其目的不外乎以下几点:
1.太寂寞(注意,不是孤独)了,需要安慰。当然,也不一定会发信息到朋友圈,这类人估计会同步信息到各个微博,博客,Facebook什么的(漂流吧,我的寂寞和我的泪!)。
2.可能希望被某些人看到制造点影响力,比如让经理看到自己大半夜的电脑屏幕上有个Word文档,这样可能对自己加薪升职可以制造些筹码啥的...
3...我不多扯了,这些话题与本文无关!

你希望别人看到你发的信息,你希望别人评论你的信息或者转发你的信息,你希望得到关注,你希望获得一种存在感,在人世嘈杂中,你很寂寞,你害怕天黑...
--------------------------------------------
以上有买有卖,你来我往,写者有心,读者有意,看似非常和谐,就算是有人在朋友圈卖东西,相信也是不敢恶意刷屏的,偶尔发个链接啥的也要用哀求的口吻。但是如果你加上我,就不一样了,注意,请不要屏蔽我。你会看到以下的信息:
我:
温州老板是傻逼!
我:
我是傻逼!但这并不意味着其它所有人都是智者!
我:
赐予我水母吧,我是带鱼...
我:
温州皮鞋,下雨进水不会胖!
我:
不是经理的博士,不是好经理;
不是博士的经理,不是好博士。
我:
.....
我:
....
我:
.....
我:
....
我:
.....
我:
....
朋友3:
我要崩溃了,谁可以来帮帮我啊救救我!
我:
都是傻逼!
我:
.....
我:
....

你10分钟的大脑精力,全部被我占据!你不得不小心翼翼的往上翻屏,生怕漏掉了其它人发的重要信息(比如馈赠,求助之类的),10分钟时间转瞬即逝,只要我能保证在其它人发的最后一条有价值信息后发的所有信息够你玩10分钟的,我就制造了严重的Buffer Bloat!Buffer就是你的大脑!在这10分钟时间内,你不能刷刷刷地掠过我发的信息,你必须小心翼翼地去”过滤“每一条信息,因为在你看到这个信息是我发的之前,你不能确认它不是你其它的朋友发的!
        然后,你的大脑崩溃了!这就是拥塞崩溃!哦,对了,你可以从此屏蔽我,但现在还不是时候,因为我接下来还要再讲讲网络突发。
        如果说上面描述的我的行为是一种恶意制造Buffer Bloat导致了你的脑爆,那么下面的这种方式,则是一种正常的测试,我收回我的恶意。
        前几天,真的是前几天,我做了一个实验,那就是把我10月份以来发的所有朋友圈信息,全部删除,然后将它们全部在昨晚一次性发布。在删除之前,我的信息看起来是下面这个样子:
我-2016/10/01:
今天假期第一天,带着小小出去玩,记得去年的这个时候,我还在上海,时间过的好快啊!
我-2016/10/03:
假期也不能忘了学习,今天写了一篇文章,欢迎拍砖!【我在博客上的新发表的一篇文章】
我-2016/10/07:
假期最后一天,跟小小一起去爬山!小孩子体力比我好!【照片】
我-2016/10/15:
编程对抗赛报了名没参加,因为我不会编程,拿了一件衣服走人...
我-2016/10/19:
下班遇暴雨,漫漫回家路!
我-2016/10/19:
华尔眼中的最后一枪,来的有点早了
我-2016/10/20:
多年前写的代码,目前还在线上跑着...【一个代码截图】
我-2016/10/22:
【展示一组自己在家做的一顿饭】
.....
我将以上20条左右的信息删除,然后统一在昨晚同一时间发布,以下可能是你在随后看到的朋友圈:
我:
今天假期第一天,带着小小出去玩,记得去年的这个时候,我还在上海,时间过的好快啊!
我:
假期也不能忘了学习,今天写了一篇文章,欢迎拍砖!【我在博客上的新发表的一篇文章】
我:
假期最后一天,跟小小一起去爬山!小孩子体力比我好!【照片】
我:
编程对抗赛报了名没参加,因为我不会编程,拿了一件衣服走人...
我:
下班遇暴雨,漫漫回家路!
我:
华尔眼中的最后一枪,来的有点早了
朋友2:
.....(我也不知道你的朋友发了什么)
我:
多年前写的代码,目前还在线上跑着...【一个代码截图】
我:
【展示一组自己在家做的一顿饭】
.....

虽然,我的这一组信息或多或少都是有点意义的,然而,这绝非你所想看到的结果,因为你更多的看到所有朋友们发的消息,而不是我一个人发的。你的大脑天生有一个负载均衡机制,所以你非常讨厌任何形式的刷屏,不管是恶意的,还是像我上面那样一次性发很多的。
        但是你又能做什么呢?跟上次我恶意刷屏一样,你不得不一条条过滤这些信息,即便你不想看,你也得先确认它就是我发的,而这些动作,需要的是时间。在做这个“将10月1日至今的所有朋友圈信息删除后集中发送于此时”之前和之后,迄今为止我发送的信息总量完全没有变化,变化的只是之前是一天1到2条,此时是同一时间几十条,这对我而言,完全无所谓,但是却对你产生了非常不好的影响,记住,这种非恶意的集中发送导致你的脑爆,也是Buffer Bloat!
        好了,让我们回到现实!
        你使用的是微信,伟大的腾讯帝国的微信产品,所以你根本无需担忧被我刷屏!你可以选择从此以后屏蔽我,或者直接将我删除出好友的行列。如果你只是关心你发送的信息有没有被人回复而不关心其它人的信息,那你大可不必刷圈,微信自带了提醒机制,关于你的信息,只要有新的动态,就会单独提醒你,而无需你自己轮询查看。然而,你也只能在微信,以及类似的微博中享受这种服务(微博也有提醒机制,并且如果你特别烦某人,可以选择不再关注),这些产品,你可以看作是互联网时代的基石,让我们回到30多年前的纯粹TCP/IP时代再来看刷屏问题。
        请把一条一条的朋友圈信息看作是数据包,请把你的大脑看作是交换节点路由器,交换机或者目标端主机,非常糟糕的是,情况是一模一样的,然而不幸的是,路由器,交换机或者目标端主机们无法“屏蔽”或者“删除”那些造成Buffer Bloat的数据包!这些数据包有些数有意的,比如流氓UDP以及中国境内一切以TCP加速为目的的厂商所产生的流量,有些是无意的,比如几乎所有的TCP实现所发出的数据包(Linux的TCP没有实现Pacing机制,所以数据全部是在一个while循环中突发出去的,Pacing机制需要底层的Qdisc层来支持)。
        在继续下文之前,请不要扯防火墙,类比防火墙会“屏蔽”那些不想看到的信息。因为,防火墙要想屏蔽谁,首先也必须看到它并识别,而这一切,需要的是时间!你难道不知道网络中防火墙越多,延迟就越大吗?

拥塞控制的本质意义

你现在理解Buffer Bloat了吗?我想你已经理解了。然后我告诉你,Buffer Bloat导致了几乎全部的拥塞!在微信朋友圈的例子里,你知道怎么避免自己的脑爆(大脑的Buffer Bloat)吗?
        我们回到30年前,假设那时已经有了微信,已经有了你和我,并且你我是朋友,你无法屏蔽/删除我的前提下,避免Buffer Bloat的办法是什么??
        唯一办法就是,教育我,安慰我,祈求我,恐吓我不要再刷屏,不管是恶意刷屏还是无意的一次性发太多信息。除此之外,如果你有别的办法,我恭喜你,你已经找到了一种拥塞控制的方法,如果方便,请告诉我,如果经常看我的博客,应该知道我的邮箱,如果不知道,请搜索dog250所有与内核模块相关的,在代码中会找到我的邮箱,请告诉我你是怎么做的,昨天意外获得了几百块的红包,如果你能告诉我你的算法,我会发红包给你,真的!
        是的,让刷屏的人不刷屏,似乎是唯一的避免Buffer Bloat的方法。是的,拥塞控制的本质目的,就是避免Buffer Bloat,避免突发!请张大眼睛注意,拥塞控制的目标不是为了让你提高性能!绝对不是!相反,拥塞控制的目标是保障公平,避免不必要的消耗,这会达到一个典型的非零和均衡点,这是典型的中国式思维所不能理解且排斥的,然而事实就是这样子。
        带着一种错误的思路,大多数人在优化TCP的时候,眼睛死死盯着“窗口-时间”曲线的凹点,希望能填平它,却几乎根本上忽略了凸点,这是非常严重的错误。凸点意味着什么?凸点意味着上升不成功掉下去了,为什么掉下去,因为资源不足了,此时意味着发生了拥塞,典型的AIMD的锯齿尖尖的位置,就是这个凸点,这个点上发生的典型事件,就是丢包!
        和错误的思路相反,拥塞控制需要注意的是凸点,而不是凹点!
        以上说的是做TCP优化的一个惯用的伎俩,那就是见缝插针,只要能多发点数据,那就多发,这十分类似道路上那些傻逼司机到处变道,变来变去其实快不了多少一样的道理,这些变道司机的思维其实特别原始,它们只是只看眼前的阵势,操着自己还行的驾驶技术变换到空闲的车道,然后等空闲车道拥堵时再变回来,非常遗憾,这招不奏效!搞不好还要来一个令人悲伤的刮擦。
...

真正的拥塞控制要做的是什么?

真正的TCP拥塞控制要做的是,要判断在什么情况要少发数据,而不是多发!这不是一个自私的系统,这是一个博弈或者运筹的反馈系统,你的每一个行为都与全世界有关,这不是一个你能全面管控的自闭系统,这个反馈系统里面,你甚至都控制不了自己,你唯一能控制的,那就是自己在发现异常的时候尽量少发数据,评价算法好坏的指标就是你能否做到“多么恰到好处的少发数据”!也许你会说,TCP中基于时延的算法比如Vegas完败于基于丢包的CUBIC算法,而且Vegas就是按照我上面说的那种,发现异常就减速。你的疑问我很理解,但我要告诉你,CUBIC是错误的,CUBIC玩的是庞氏骗局,它相对于Vegas的高速传输行为事实上是一种透支行为。透支的是什么?透支的是“乘性减窗口”!CUBIC之所以还算优秀,那是因为几乎大家都在用它。世界上很多的服务器部署了Linux系统,而CUBIC又是Linux默认的拥塞控制算法,为了表现的好像在照顾那些弱者,CUBIC还引入了蹩脚的Friendly特性...
        那么谁是正确的呢?
        我认为BBR算法是正确的。因为它天生就按照无Buffer Queue的原则(一旦发现产生了Queue,就Drain掉它!)来设计,既然没有Queue,那自然就不会Buffer Bloat了,它是对的吗?这TMD才是真正的拥塞控制啊!
        也许你又要问了,既然正确的拥塞控制算法要避免Buffer Bloat,既然我说BBR避免排队的行为是一个“本质上正确”的行为,那么网络中的队列到底是干什么用的呢?好问题,下面一节我想详细展开这个问题。
--------------------------------------------

分组交换网络队列的本质与拥塞控制

分组交换网和电路交换网完全不同,它采用统计复用原则,意味着在一个处理节点,数据包分组的到达的分布是符合泊松分布的,这就是说,队列是一定会存在的(泊松分布,马尔科夫到达决定了队列一定是存在的,必须在交换节点分配队列缓存)。
        这好像又回到了之前写的文章中描述的那些老路上了,要折腾一大堆数学公式,要搞一堆术语...但是你会发现,这篇文章写到这里还没有出现任何关乎专业术语的描述,以后也不会有,所以说,我打算通俗地解释一下为什么队列或者说排队现象是一定存在的,这里我不用泊松分布或者排队论的术语。这里我以城市快速路为例。
        道路交通系统是一个典型的统计复用的分组交换系统,其实早在TCP/IP分组交换网络之前,道路交通系统就已经存在了好几千年了,经典的例子就是古罗马的道路。但是年代久远了,扯那些就有点卖弄学问的意思了,所以说,以我们眼前的例子描述或许更加方便。
        本质上讲,队列是由于处理率小于到达率导致的!
        那么问题出现了,你让处理率大于等于到达率不就可以了吗?这是一个典型的学究式的反问。事实上,任何人都做不到让处理率大于等于到达率。原理很简单,你根本不知道到达率,到达率是事后算出来的,也就是说只有当到达的车辆或者数据包被处理了之后,才知道此时的到达率是多少,注意“此时”这个关键词,所以说,到达率是一个瞬时值,而不是一个持久的值。如果说把一段时间的所有的到达率采集下来,你会发现,这些到达率的值分布在一个可观测的范围内,数学家们仔细研究了这种分布,发现了规律,名曰泊松分布。
        只要你给定一个处理率,那么统计意义上,就一定会有到达率超过该处理率的概率,不管概率多么低,它是可能的,一旦发生这个事件,就需要一个队列来缓存未被即时处理的事件。
        现实中,大胆的设计者可能会说,把处理率设置成一段足够久的时间中采集到的到达率中的最大值不就可以了吗?至少99.9%的可能可以避免排队!这样可行吗?也许你已经知道了答案,不可行,因为这很浪费资源。但我的回答不是这样的。之所以不可行并不仅仅是浪费资源这么简单,而是基于统计复用的系统中,这样的设计是不可能实现的!我现在来简单证明一下这是为什么。

        我以全互通十字立交(靠右行驶)作为背景来证明这是为什么不可能设计出来的。要证明这种将处理率取最大到达率的系统是不可能设计出来的,我们就一步步地去设计它试试看,然后就知道为什么不可能了。请看下图:




注意上图的红线,有这么一种可能性,那就是1,2,3号车道同时有车辆要汇入4号车道,必然有两辆车要排队等待,为了消除排队,按照大胆设计者的思路,正确的方案应该是下面的样子:




是不是感到宽敞多了呢?然而,同时是不是也看出问题了呢?
        我们知道,条条大道通罗马的意思是所有的道路都是想通的,一个成熟的快速交通系统应该是没有断头路的,即没有路之尽头,这就是为什么几乎所有的快速交通系统都设计成环状加辐射状的原因。整个道路网是一个完整的系统,当然也就不止上图中那么理想化只有一个互通立交了,它的局部应该是下图的样子:




请把这张图向上继续画下去,自己算一下过10座立交桥的时候,向北的车道是多少根!
-------------------------------------------
但是仅此只是说明了这么玩特别浪费资源,在市政府有钱的情况下,就算100根车道又如何呢。最大最好玩的问题要出现了。请试着把上面的图画成环试试....




注意蓝色线,它标识了一种可能的车流汇集方向,按照避免排队的大胆设计,车道数会指数级增加无穷大!无穷大是一个抽象的数学概念,它并不真的存在(古人的googol是多少呢?)。所以说这种设计是不可实现的!
        这是一个咬尾蛇的困境,一条蛇咬住自己的尾巴,想把自己吃掉,请问结果如何?仔细思考这个问题,你会想通宇宙和人生的!
-------------------------------------------
到底哪里出来问题呢?为什么会进入无穷大的虚无困境呢?这背后的数学推理比较复杂,但是简单的说,那就是系统设计偏离了统计的均衡点。这个均衡点是一个不稳定的凸点,一旦稍微偏离,就会滑向万丈深渊!遵循统计均衡点的设计应该是下面的样子:




非常平衡,非常稳定,然而带来的一个问题就是排队!事实上排队并不是问题,而是一种所有的统计复用系统本质上存在的一个属性,它的存在保证了系统的稳定和平衡!所以说,基于统计复用的系统,就叫做排队系统!
        除了道路交通系统之外,它还包括TCP/IP网络。
        每一个交换节点,都会有一个队列系统,不考虑碰擦等交通事故,也不考虑施工以及收费站等因素,正确的道路系统的排队全部都在匝道上,这里是道路交通网络的交换节点,类似TCP/IP网络中的路由器,交换机。在TCP/IP网络中,数据包不会在线缆中排队,只会在交换节点排队,这个与道路交通网络几乎是一致的。在道路交通网络中,发生在道路上的排队几乎全部是由冲突导致的,在TCP/IP网络,这点非常不同,TCP/IP分组交换网中,线路上的冲突会导致数据包的彻底丢失(参考CSMA/CD原理)而不是排队,因此就导致了两种模型的出现,即要么靠重传数据包解决线路上的冲突的问题,要么就彻底忽略冲突导致的数据包丢失,这就是TCP和UDP两种传输控制协议的设计理念的根源。
-------------------------------------------
说完了队列存在的根源之后,你应该已经默认了排队是不可避免的。那么队列是什么样子的呢?
        取决于交换节点的容忍度,队列分为深队列和浅队列。以刷朋友圈为例,在你发现有意义的信息或者干脆彻底放下手机干别的事之前,你能忍受我多少的刷屏,这决定了你的大脑队列的深度。
        在快速路交汇点的匝道,你会发现它们长短不一,匝道修多长并不是随意的,它是由队列长度决定的,而队列长度又和交通量有关。雨中的回家路,我无数次经过南北高架与汶水路的交汇处,那个匝道设计的不太合理,你能给出一个合理的设计吗?
-------------------------------------------

为什么高速网络要设计成环状

你可能已经发现,几乎所有的高速网络都是环状的,比如城市快速路,IP骨干网等等。其实,这背后是有原因的。
        我是搞IT的,对网络方面比较熟悉,借此文我的目的是帮大家理解队列以及TCP拥塞控制背后的理念,在这一节,我依然不去深入描述路由器内部原理以及TCP拥塞控制算法的细节,那些细节是等你彻底弄懂了本质之后才需要去看的,诚然,即使你没有弄懂本质,甚至你根本上对本质一无所知,你也能看懂那些原理或者代码的细节(大多数高等教育出身的科班生不都是这样么?),但这种学习方式是不正确的。不多说,让我们开始吧!
        为什么要设计成环状呢?答案在于避免拥塞!
        已经在深圳一年了,这一年中我见证了这座城市的快速发展,我比较不关注房价菜价之类的事情,这些与我无关,我只关注道路。每到一个新的陌生的城市,我首先会一连几天看其地图,然后等熟悉了以后,没事就会看。看什么呢?看城市的道路。这里我举的一个例子就是深圳城市快速路系统的一个反例,我要告诉大家快速交通系统不按照环状设计是错误的。
        首先我们看一下深圳的快速路系统,我给一个不是详细且不是很全的简图,但足够说明问题了。图中红色道路为非快速路(会有红绿灯),但它们都是交通要道。现在我们来找下拥堵点,其实不用找了,在深圳的人没有不知道的:




这些拥堵点有目共睹。现在我们来分析一下。
        你能在上图中找到几个环?很明确的可以看出,深圳城市中心,那几个红色圆圈的位置都不是环的一部分。因为我就在科技园上班,所以我们来分析一下附近与这个园区上下班流量息息相关的沙河西路/南坪快速的交汇处拥堵点。
        南坪快速与北环大道不成环,意味着经南坪快速西行进南山的车辆必须在南海大道或者沙河西路分流南行。以经验来看,人们都喜欢抄近路(非常遗憾的是,IP路由也是这个原则!)自东向西的车流不会绕道南海大道南行的(他们是宁可等也不愿绕,这是典型的透支第二类缓存的庞氏骗局!!),那么南坪快速沙河西路匝道会异常繁忙,事实上也是这样!
        下南坪快速进沙河西路南行出口处,有个红绿灯!就是这个红绿灯造成了该匝道的猛烈排队!
        因此沙河西路从南坪快速到滨海大道区间的快速化就是一个非常合理的需求。这样的话,沙河西路,滨海大道,香蜜湖路,北环大道,南坪快速,沙河西路就可以成为一个环,完全做到主道通行,匝道卸载的目的。
        一旦将沙河西路改造成快速路,那么沙河西路就变成第一类缓存了,没有时间墙,纯流量卸载的缓存。不然的话,这里就是一个带有时间墙的第二类缓存。
-------------------------------------------
接下来,在阐述统一的结论之前,我再给出上海市的城市快速道路网,毕竟那里是我生活了7年的地方,家底还在那边可能以后也会再回去。在下图中,我用红色圈圈标出了几个典型的拥堵点:




因为我的家在嘉定,所以我对附近的道路更熟悉些,就以那边的为例子剖析了。
        我们仔细看图中实心红圈标出的拥堵点。我们把上海的这几个拥堵点和深圳南坪快速/沙河西路这个拥堵点做个比较,能看出什么规律吗?其实,它们都遵循下面的模式:




即快速道路匝道下来的流量“侵入”到了不同向的其它非快速道路,我把这种匝道简称为“非同向侵入式匝道”,这种流量会在两个方向“打扰到”另外一条与之交叉的非快速路上的流量,而且,这种流量入侵几乎总是突发式的,上海外环/沪太路那里,跟南坪快速/沙河西路一样,平时非常好,只要到上下班高峰期,绝对堵成翔!
        和上面的那种非同向侵入式匝道相对,上海的很多高架路则完全不同,高架路上的匝道是下面的样子:




即便是高架下来的流量,也是与地面道路同向的,并且仅此一个方向,不管是高架上还是地面道路,其通行方向一致,表明同一时间内其通行目标是一致的,地面道路可能仅仅是在最后一公里卸载了高架上的流量而已,我把这种匝道叫做“同向卸载式匝道”。在深圳,滨海大道,滨河大道也是这样子的设计。
        有了以上的概念,就很容易理解非同向侵入式匝道上为什么会堵成翔了。要做的只是把快速路围成环,这样就能将非同向侵入式匝道改为同向卸载匝道了,深圳南坪快速/沙河西路的方案如下:




同样的道理,上海沪太路也要快速化:




-------------------------------------------
这跟成不成环有关系吗?看似没关系。仔细看上面两图中的1+1=2以及0.7+0.3=1这两个关系公式,你能看出点什么吗?
        请注意,环意味着什么?环就是一个圈,拥有每一个方向的圈,不管拐到哪个方向,都在这个圈上,环意味着没有尽头。这似乎不太好理解,那么我们来看下什么不是环。线不是环,它是有尽头的,在一个拥有尽头的统计复用的网络中,队列将是无限大的,因为这里有一堵墙,时间墙!作为最后一个例子,我们来看看我家门口附近的一个拥堵点,那就是上海沪嘉高速/叶城璐交汇处。这里是沪嘉高速的尽头(其实也可以理解成一个位于进入G1501主道收费站右边的一个匝道出口)!只要沪嘉高速上有哪怕一点进入嘉定城区的流量,这个出口的位置一定持续性堵成翔!为什么?很简单,出口出去后都是普通道路,而沪嘉高速则是限速80km/h(改造前是120km/h)的城市快速路,到达率远远大于处理率!那为什么不是一直堵到中环汶水路呢?这里到达率的泊松分布可以解释,我就不解释了。
        沪嘉高速终点这个地方,是一个非常典型的路之尽头,其拥堵也非常好解释。对于深圳南坪快速/沙河西路这个点,你能意识到它事实上也是路之尽头吗?
        虽然在物理上,这里只是一个通往沙河西路的匝道,但事实上,再往前走就是南头了,中间再没有匝道,绝大多数的进入西丽或者南山科技园的车辆都会在沙河西路出口下去,因此这里是一个事实上的路之尽头,所以说,这就解释了为什么这里会这么堵。怎么办?围成环。将南北向的沙河西路也纳入东西向的南坪快速的一部分,消除掉这个尽头即可。消除了路之尽头,也就消除了在路之尽头典型的线头拥塞问题!
-------------------------------------------
现在可以下结论了。想要快速,就必须成环!因为只有围成环才能将侵入式流量转化为卸载流量。这里,对于道路交通网而言,宁可等也不愿绕可能是由人的心理决定的,这是典型的透支第二类缓存的庞氏骗局!!遗憾的是,不管是城市中的车流,还是OSPF等路由协议,或者CUBIC拥塞控制算法,都在玩这种透支行为。
        如果你有时间,研究一下IP骨干网的拓扑,然后Trace一下几个关键节点,观测到达它们的RTT变化情况,你会发现,这就是一张IP数据报文的道路交通网!与现实中的城市道路交通网络几乎是一致的。而且在司机越来越依赖导航的节奏下,两个网络会越来越一致。向我这种偏偏不按“最短路径”走的人越来越少了,因此能主观上避开拥堵的也会越来越少。
        说点题外话结束本节。导航是机器控制人的一个典型例子。之前都是司机自己看纸质地图,然后自行决定怎么走,现在还有几个人能看懂地图?!大家基本都是听着“前行300米后向右边进入辅道”这种指示开车的。姑且不说拥堵,更加严重的事情都可能发生,把人车带进沟里的还少吗??
        IP路由表是OSPF算出来的,现在你开车出行的路线也是OSPF算出来的,大家同一时间堵在同一条路上,统一拿出手机开始刷刷刷,于是乎大量突发的数据包统一发送到最近的同一个基站,然后统一到达同一个路由器被分发交换,于是这些数据包也堵在同一个路由器里...车在路上等啊等,道路还是不通,人在车里刷啊刷,页面却怎么也不肯出来!两个网络同步拥堵。

该结束了

本文写到这里该结束了。其实还有很多话题没有展开,比如关于布雷斯悖论的话题,其实也是很有意义的。关于此话题,我建议大家研究一下韩国首尔拆路治堵的例子,然后试着分析一下上海沪翔高速与沪嘉高速为什么没有互通。
        拥塞控制是一个合作式的控制机制,而不是一个对抗式的控制机制,因为本身统计复用的网络就是一个合作式的系统而非对抗式的系统,合作才能共赢。所以说,在这么一个拥有蝴蝶效应(你的行为的结果与全世界有关)的合作系统中,所有的小聪明汇总的结果就是一场大拥堵。正如车辆堵在路上无法飞走一样,数据包在路由器队列里也无法排出,只能等。发现拥塞总是滞后的,只有当拥塞实际发生的时候才能发现拥塞,但此时已经晚了!于是人们希望可以预测拥塞,那么预测也就只能基于历史来预测将来,本来所有开车的人都知道哪哪路段在什么时间会堵车并视情况而绕开,但自私的小聪明让他们执意选择去添堵,这是一场自私者之间的博弈!
        OSPF协议按照度量计算最短路径,然而度量本身怎么去度量?这就是问题。这个问题导致了网络拥塞。人们普遍认为路由的收敛速度是一个性能指标,越快越好,但我的观点与此不同,我觉得越收敛的路由越容易发生拥塞,因为大家算出来的最短路径是一致的。
        BGP路由协议天生就有抗堵的功能,然而大家都说它是基于Policy的,不是自治的,SDN也能全局控堵,然而大家指责它是集中独裁的,而非“失控”的,在“失控”的互联网世界,拒绝独裁。
        争议总是不断,所以说拥塞控制更像是社会科学的范畴而非自然科学。就在上周五,我跟同事开了个玩笑,我们的周五下午总是非常轻松,如果大家都没啥事,晚上还能聚餐,上周五的时候,大家商量去吃饭,4点多出发,由于几个同事工作上有点事要处理,所以就分两拨人走,处理工作的晚点出发,正好赶上下班高峰期堵车,吃饭的地方又没有地铁公交,只能开车或者打车,没人开车只能打车,我给了个建议,打100辆车,把自己复制100份,总有一辆能到!
        虽然在道路交通网上,你不能把自己复制100份,你甚至不能把任何一件东西复制100份,但是TCP/IP网络是可以的。于是各种令人作呕的加速方案就出现了,一个包发两遍是一种最简单的方案,假设丢包率是5%,那么两个都丢的概率就是5%*5%了,是这个数字化的概率吸引了设计者,另外还有抢着发包的,观察若干连接的吞吐量/时间曲线,发现凹点就查代码,打日志,重现凹点,看看到底发生了什么,最终的目的是填平这个凹点,这个思路比一个包发两遍聪明了很多,还有更加激进的,直接忽略拥塞窗口,眼里容不得窗口下降,甚至连对端通告窗口都忽略,没事了就要发几个数据包...唉!太悲哀了。幸亏现实中的人和物品不能复制,万一要是能了,在我们这个伟大的地方,道路真的就全部都成停车场了。
        拥塞全部都是Buffer Bloat的后果,有一种DDoS导致的Buffer Bloat你们听过吗?这“归功”于我们的专利制度!只要是比较有名气的大公司放出几个专利,那么就会有别的公司投入巨量的人力物力来“偷偷摸摸”实现这个专利,因为在中国人的眼里,越是你拼命保护的东西,就越容易引贼惦记。我们反其道而行,累死那帮贼!以大公司名气,放出几个根本没有价值和意义的专利,吸引那些别的公司去偷摸实现,这样会消耗掉他们大量的资源,导致他们根本干不了正事,是不是跟刷屏的效果一样呢?
        我以刷屏开始本文,以类似刷屏的DDoS来结束本文。
        看来事情还没有结束,虽然事情还没有结束,但是本文真的该结束了!
2 0