家用电器为了防止电流过大,都会有保险装置,当电流过大时,自动切断电流,防止电器损坏, 防洪大坝的水位超过了警戒线,会开闸泄洪,防止大坝崩溃. 而我们的服务系统如果一旦流量过大(用户或请求超过其处理能力),很多情况下,都把自己搞挂了,很显然,我们设计系统时没有像我们的工业及建筑领域那样成熟的引入自我保护机制.稍不注意就把自己搞挂了.
一个系统的处理能力是有限的,就如一个车站在车次一定的情况下(车辆一定,运力一定),每天可以输送2万名乘客, 如果逢年过节,赶上春运,一天来了25000名乘客,怎么办,多开几个售票窗口,多开几个进站通道,有用吗,显然,是没用的,肯定还有5000名乘客当天运送不了, 如果每天如此,持续10天,那么将有50000名乘客还在排队,假设所有的乘客都是按照先来后到的顺序依次上车,那么第11天来的第一名乘客,需要2.5天后才能乘车(需要等到前面50000人走完才能轮到自己)
假如我们的一个服务系统A处理的每一个请求都依赖一个下游系统B,系统B的吞吐量为2000/s . 不管你A系统开多少线程,B最终一秒钟为你服务2000次. 而且B的这个服务水平是无法因为A的优化而可以提高的(不管你怎么设计车站,和售票窗口,进站通道,你只有100俩运输客车,一天最多装2000人开走)如果A系统的请求数忽然增至2500,如果所有的请求都是先入队列,假设队列长度很大(可容纳10万)再依次处理。(其实基本上所有的系统也都是这样),那20秒后,就会积压有10000个请求未处理,那么第21秒过来的第一个请求,需要等到前面10000个请求都处理完,也就是5秒中后才能处理,如果A上游的系统读超时为5S,那么在系统过载的那一刻开始,第20秒,对于A的上游系统来看,整个A系统已经完全不可用了.假设这是个面向用户的互联网服务,那么系统目前的现状就是,当系统过载后(请求数超过了2000/s)20秒后的第一个请求需要5秒后才能被响应,用户的往往在等待若干秒发现系统没响应时就会不断的重试,导致了新的重复的请求越来越多,而之前的请求早已没有意义,可我们的系统还是很认真值守的处理之前的请求.
看起来,这就已经是个死循环了,无用的请求在大量占用系统的资源,新的请求被排在了最后,需要很久才能被处理,用户得不到响应,开始重试,请求越来越多,直到整个系统完全不可用。
那么我们怎么才能做到系统的自我保护呢,最简单有效的方式就是丢弃无用请求,当第一秒2500个请求过来时,我们只处理2000个请求,其他的请求可以在队列里直接丢弃,或者直接控制队列的入队速度,那么我们的系统还能正常的按照2000/s的水平提高服务,只是部分请求,也就是 1/5的请求被丢弃,第二秒也是这样,量力而行,只处理我们系统能够承受的服务。而不是尽力而为 . 对于超出自己处理能力范围的请求,要勇于拒绝.系统的能力只有这么多,既然无法提供2500的水平,那就提供2000的水平,最起码我们的服务还能服务4/5的请求.不至于像前面所述那么全部瘫痪.