因为疫情的影响,在家一个月了,火锅、烤肉、烧烤、奶茶已经不认识我是谁了。往往翻到一点关于美食的东西,就馋的不行。终于等到复工,当晚就点了一个火锅外卖,在家准备解解馋。如今火锅外卖挺方便的,若是不想洗锅,能够点一次性锅,点的食材也都是切好的,我一瞬间点了牛肉,猪肉、牛肉丸、鱼丸、虾滑、毛肚、黄喉、土豆等食材。等到外卖到来,摆好全部东西,准备开吃,但是吃着吃着,我发现味道并无想象中那么好了,难道是我一个月就已经忘记了火锅味?后来我发现是由于我把不少食材一古脑儿都放在锅里了,而在外面吃的时候会根据食材的不一样来决定烫仍是煮,煮多久等等。就拿出名的重庆九宫格火锅来讲:算法
中心格:温度高,就是用来烫的,适合比较容易熟的食材,如毛肚、肥牛、腰片等。markdown
十字格:温度中等,用来入味,适合下虾滑、其特点为边煮边吃等。并发
四角格:温度低,适合长时间蒸煮须要入味的食材,好比脑花、肥肠、鱿鱼等。ide
针对不一样的食材有须要不一样的火候,这可能就是爱情中常常讲的很悬的“合适”吧。由于一次性锅比较小,所能放的食材比较少,因此不少时候我就在等肉煮熟,在等待中以为这很是像限流的场景,由此对限流展开了一阵思考。高并发
机器在单位时间内所能承载或者处理的请求数是有限的,这个阀值取决于机器的总体性能以及代码中这次请求所要处理的逻辑。在高并发的场景下,若是不对请求进行限流,可能会出如今单位时间内大量请求涌入某台机器实例,致使大量请求在队列等待,或者致使机器资源耗尽,甚至是服务挂掉。除了防止因为流量洪峰致使服务被击垮之外,必定的限流也能保证整个集群的QPS最佳,由于若是一台机器实例挂掉,整个集群就少了一台机器处理请求,别的机器就要分担更多的请求,若是流量洪峰持续时间过长,会拖垮整个集群。咱们知道请求能够被拒绝,可是服务绝对不能所有挂。因此为了保证服务的高可用,限流是必不可少的一个方案。性能
目前耳熟能详的限流算法有:spa
介绍这两种算法前先拟定一个场景,见下图:code
我脑海中想要吃某个食材,就会去看火锅里面有没有这个食材已经被煮熟,这是我发送的一个request(假设一个食材只能被看成一个request发送),须要火锅给予我response,而火锅若是没有对应的食材,则会去食材库查看是否有对应的原材料,这个时候就是火锅向食材库进行请求。这是一个很简单的调用链。orm
漏桶算法用上面的场景就很好理解,当火锅瞬间想要毛肚、牛肉等N个食材,也就是食材库会接收到火锅的N个请求,可是火锅在1s内只能煮Q个食材且Q<N,也就是火锅能处理的响应只有Q个,假设食材库存最多能处理的食材是M个,而且N<M,那么其实食材库是能够承受住这么多的请求的,可是当食材库在1s内把N个食材整理好返回给火锅时,火锅并不可以煮得下这么多,这个时候火锅就会溢出,反观计算机,也就是在单位时间内provider端返回响应时consumer端并不能承受住该回调洪峰,致使consumer端被击垮。队列
这个时候就能够用漏桶算法来解决这类问题,它能够保证火锅每一秒想要的食材只能是t个,也就是火锅的请求速率是恒定的,那么在单位时间内,食材库返回的响应也能得以控制,这样就不会形成火锅溢出,也就是服务被击垮的状况。
漏桶算法虽然能够对回调洪峰作流量整形,可是对于用户洪峰,服务依旧会有被击垮的风险,好比当我1s内想要吃r个食材时,可是r>Q,也就是火锅没有办法承受住我这么大的请求量,那么火锅依旧会被击垮,这种时候不该该用漏桶算法去限制我想要吃的数量,由于限制了我单位时间想要吃的食材数,就等同于每个单位时间可以发出请求数量就被限制了,而在一个产品中,若是每一个用户的请求速率都被限制成同样而且并不快,那这样的产品将很难被接受。
对于这种用户洪峰,令牌桶算法能够有效的对流量进行整形。仍是拿火锅这个例子,上面不是说火锅在1s内只能煮Q个食材吗,那么我就把这个锅用挡板分割成Q 个空间(假设一个空间只能煮一个食材),有点相似于重庆九宫格火锅。当我瞬间想要吃X 个食材时,每一个食材都从一个空间里面去拿,若是那个空间是空的,则火锅能够煮我想要的食材,若是瞬间整个锅没有空的空间,则其余请求都被拒绝,当一个空间的食材被我取走后,该空间就会被释放,又能够用来接受食材请求而且煮食材。这就是令牌桶算法。
除了对两个限流算法从新审视了他们的应用场景外,还对限流粒度也作了思考,从粒度上来讲一次请求,无非就是一次RPC的方法调用,因此最小的粒度应该是方法级别的限流,也就是上述火锅案例中,针对我想要吃某个食材这个请求进行限流。若是对每一个方法都配置不一样的阀值,整个系统的维护成本就会大大增长,因此通常只是对特殊的方法采用更细的阀值配置。除了方法级别的限流外,更上一层的就是服务级别的限流,一个服务会有不少个方法,有时候咱们不想要对一个一个方法进行限流,可能存在某个服务在一些商城促销活动等场景下须要限流,而这时候但愿可以直接对某个服务进行限流,而并非对服务中的方法进行一一限流,服务粒度的限流是用的最多的。再上一层就是对集群进行限流,也许是某几台机器的性能不佳,因此不能跟正常的机器配置同样的限流阀值。面向整个集群的限流通常是用做兜底的保护措施,使系统不会被忽然流量洪峰击垮。