任何一个服务都有自己的能力上限(QPS上限)。为了服务有良好的健壮性,当请求超过能力上限时期望服务仍然健康的对外提供服务,而不是资源耗尽服务不可用。该wiki提供一种通用的限流方案,该方案不仅适用于提供http服务的项目,也使用于提供thrift接口的服务(OCTO已经提供了限流支持)。
本质上存在两种限流的机制,一种是基于桶容器均匀流速的方法,另外一种是基于令牌取号的方案。
思路很简单:有一个容器桶,该桶里面装有需要待处理的request请求。桶均匀的按照一定的流速(处理请求服务的可接受处理速度)将请求喂给服务。
优势:
劣势:
思路比较巧妙:有个号码桶,里面装的是号码。有一个生产者按照一定速度(服务的可接受速度)放号码到号码桶。
每次外围来一个请求,先去号码桶取号。如果取到号码,则对该请求做业务处理。如果取不到号码,对请求做限流处理(抛弃或者别的简易操作)。
优势:
劣势:
限流流程如下图:
问题的关键就是号码桶的设计。因为该方案中的限流并不是仅针对单机,而是针对一个服务(集群),所以一个集群需要一个号码桶。
号码桶有两种设计方案,一种是集中式号码桶,另外一种是richClient号码桶。
针对一个API,在限流系统Server端有一个对应的号码桶(可以采用redis的queue实现)。服务提供者在处理一个请求的时候先需要从限流系统的Server获取一个号码。
如果获取到号码,则进行业务逻辑处理。如果获取不到码号,则进行限流处理。
优势:
劣势:
该方案与集中式号码桶思路相反,将压力巨大的号码桶分布在限流系统的客户端(为服务提供方支持一个限流Client)。限流Server只需做指令下达就行。
号码的生产直接放在client端。这样能减轻限流Server的压力,同时减少获取号码的时间。
优势:
劣势:
每个节点针对一个需要限流的API有一个单独的号码桶,该号码桶需要满足:
当生产者生产号码速度超过消费者消费速度的时候就会导致号码过剩现象。号码过剩会带来两个问题:
因为号码桶能回收过期号码,同时队列有界。所以不会导致资源耗尽问题。
号码不足就是限流的场景。如果没有从本地节点获取到号码就进入限流分支。
节点增加(或者减少)会导致单个节点生产号码速度下降(或者上升)。
原文:http://www.cnblogs.com/xinxinwang/p/4932327.html