不知道大家发现一个现象没有,无论 12306 网站崩溃成什么样子,火车站售票大厅的售票窗口都是正常的!这说明什么呢?这说明铁道部有个内部网络, 12306 仅仅是个入口而已。如果我们把铁路内部网比作信息的高速公路,12306 网站就是高速公路上的收费站。
说到高速公路,这两天有很多新闻,据说很多高速公路入口处变成了停车场,有人在上面做操、有人遛狗、还有生孩子的、随地大小便的、犯心脏病的等等等等,总之是一片混乱,崩溃!但是入口处再怎么乱,进入了高速公路,基本上还是比较顺畅的。
仔细看看竟然和12306的情况一摸一样,12306 就是为了防止内部网络瘫痪而设立的一道调度关卡,结果和高速公路一样悲剧,都是内部顺畅,入口处卡住了。
下面我们就把高速入口和12306看做一个问题,分析分析怎么解决:
方案一:拆分,每个车次都设立一个车票服务器。
这个方案理论上绝对可以解决问题,但现实中根本不可能。想象一下,为全国任何两个城市之间都建设一条单独的高速公路,并设置单独的出入口,当然不会拥堵了,但是可能吗?就算不考虑成本问题,铁路公路部门从管理运营其他方面考虑,也不会同意拆分的。
方案二:分布式,大缓存区。
现在很多人都没搞清楚问题的实质,一上来就是分布、缓存之类的。高速公路入口难道没有分布吗?难道没有缓存区吗?
先说分布式的问题:每个大城市上高速都不止一个入口吧,这应该是一种分布式处理吧?有人说入口不够多,其实再多的入口也没用,因为不管你分布多少入口,最终所有的流量还是要汇集到那么几条主干道上去。只要流量是一瞬间大量出现的,最终还是会堵在某个地方,只不过变成了外面不堵里面堵而已。
再说缓存的问题: 每个高速入口处都有一个小广场,停个百八十两车没问题,这不就是缓存区吗?有人说缓存区不够大,好吧,建个能停十万辆车的广场,再配套上医院、饭店、旅馆、公园之类的, 这个缓存区够大了吧,有用吗?入口处就那么几个路政人员,他二十四小时不停地发卡,结果工作人员口吐白沫手抽筋了(请查找相关新闻),这是什么?这不就是系统崩溃了吗?入口的处理能力有限,再大的缓存区又有什么用???
方案三:排队
现在唯一的方法可能就是排队了,但是传统的排队能解决问题吗?人的耐心都是有限的,一般人等个二三十分钟可能还行,如果让你从日出等到日落,估计任何人都崩溃了。崩溃了怎么办?有人就开始加塞抢道、有人直接上了应急车道、有人准备原地调头,有一个人做就有两个人做,然后就是一片混乱,缓存区彻底瘫痪了,进也进不去,出也出不来,所有人就塞在那里,动弹不得。和12306一摸一样。在这样一个人多、资源少、素质也不太高(比如说买一张票,几十个人一块刷)的环境中,传统的排队好像也不太现实。
思考题:火车站进站为什么很少崩溃?
有一个问题不知道大家想过没有,过年过节时候的火车站,也是检票进站,那人山人海的,流量可比高速公路入口大多了,为什么火车站进站很少听说有崩溃的?
秘密就在于火车票上面的那个发车时间!
比如你的车票发车时间是12:00,现在是8:00,时间还早,你不会堵在检票口处死等吧!你可以先去网吧上上网、逛逛商店、吃个饭、会会网友之类的。等到时间到了,闹钟提醒你了,你再往火车站赶。
原先是几十万人依赖一个入口,现在是火车站和乘客都依赖一个发车时间,依赖反转了。一旦反转,就会发生很多变化:
变化1:检票系统对流量的处理就变被动为主动,原先是来多少就得处理多少;现在是通过调度,让流量按照时间一波一波的来。
变化2:原先的缓存区仅仅只有候车大厅那么大一点;现在整个城市都是火车站的缓存区,只到登车前才进入候车大厅。
变化3:原先的侯检、排队是一种混乱的、无秩序的、让人无法忍受的排队;现在虽然也是一种排队,但是是一种有秩序的、有调度的、体验良好的排队。
通过上面的分析,问题的症结已经很清楚了:
1、内部网络为了保证安全、稳定和统一调度,必须设置入口关卡;就像高速公路入口、火车站检票口之类的。这一点无法改变!
2、 入口的处理能力是有限的,而且只能一个一个放行,强度大了可能还会口吐白沫、手脚抽筋(系统崩溃)。这一点也是无法改变的。
3、入口对任务的处理是被动的,来多少就得处理多少,没有调度,直到系统崩溃为止。这一点是唯一能够改变的地方。
解决方案:依赖反转
高速公路入口或者12306网站,他们作为入口之所以会经常瘫痪的原因就是上面的第三条:对任务的处理是被动的,来多少就得处理多少,没有调度。
既然找到了问题所在,解决起来就比较简单了。
先说高速公路的例子:
假如你和我两个人明天都是要9:30上高速,按照原来的流程,我们两个人会在高速公路入口处排队,当然还有很多其他人。
现在, 我们提前一天将任务提交给高速公路管理部门,第二天9:05我收到短信,告诉我可以出发了;9:13分你收到短信,可以出发了。当然,时间可能不会像你要求的那么准确,但是绝对比大家都挤到入口处等待节省时间。
再说 12306 的例子:
上亿次的请求被几千台外围的服务器拦截处理以后,怎么办?一块向入口挤吗?千万不要!!
把所有的请求被缓存下来,然后就啥也不用管了。千万不要向中央服务器提交,因为入口就那么几个,主干道可能就那么一条道。
庞大的流量依赖几个有限的资源,必然会造成混乱。
那怎么办?依赖反转啊!你们别来找我,我去找你们!中心服务器主动从外围服务器上获取请求数据,然后统一调度处理,处理完毕以后再通知用户。
额外的好处:用户再也不用找几十个亲戚朋友不停地刷新页面了!
为什么?因为原先刷新页面的目的是为了挤进入口去,刷的次数越多,进去的可能性越大。
现在,你刷多少次也没用,你的数据只是被缓存起来,而不会被处理。什么时候处理,由中心服务器统一调度。
秩序恢复了,体验变好了,大家的素质看上去好像也提高了。
其实,有时候,能排队也是一种幸福!