前言
资源是有限的,预测是必要的,然而意外也是可能发生的。我们可以看到一些重大生产事故往往是被突发的流量冲跨的,对流量的治理和防护就尤为重要。防患于未然,保障服务高可用,需要引起重视。另外我们也需要对标行业一流治理能力,本文介绍下高可用中另外一个成员,集群限流。
一、集群流控使用场景
场景一 需要控制调用总量
某些场景下,需要对APP应用某些资源(接口)的调用总量设置限制。例如:该APP由于依赖了第三方提供服务,第三方流量有限制,需要对总量进行管控。部署的节点可能扩缩容,这种单纯通过单机限流措施难以凑效。
场景二 单机流量不均衡
应用APP部署了10个节点,总流量为2000QPS,每个节点200。这事理想状态,实际可能由于负载均衡造成流量倾斜。有的节点流量高、有的节点流量低。如果只从单机限流角度限流,可能会出现一个APP应用中有的节点已经发生限流,有的负载还很低的情况。
场景三 部署节点配置不同
应用APP部署了10个节点,有的节点2C4G,有的节点8C16G。这种混合部署的场景,如果只从单机设置限流阈值,只能以配置低的压测值作为设置阈值,高配置节点会造成资源浪费。
备注:通过集群流控配合单机限流更好的应对不同场景流量防护,是流量防护中比较好的实践。
二、集群流控实现原理
实现集群流控,需要统计请求的调用总量。我们采用在应用内部选一台机器作为Token Server,用于流量的统计和token的发放。
请求流程
如下图所示,在请求链路中当服务A发起的请求调用B服务时,B服务开启了集群流控,其中一个节点作为Token Server,其他节点均为Token Client。流程如下:
- 当请求到达节点时会向Token Server发起token请求
- Token Server根据是否达到阈值决定是否发放token
- 承接请求的节点获取token后向下游调用,超过限流阈值Token Server未发放token,请求被拒绝
实现原理
集群流控的实现依然基于令牌桶实现的,下面为示意图:
工作过程
- 请求流量从令牌桶中获取令牌,持有令牌放行,否则被拒
- 假如设置阈值每秒允许100个请求通过,则请求发送速率r=100/s
- 需要令牌生产速率为1/r,即1/100每10毫秒产生一个令牌
- 令牌桶容量为b已满多余的令牌将被丢弃
- 令牌桶为空请求被拒
- 允许突发流量最大突发流量为令牌桶容量b
- 请求通过相应的令牌从令牌桶中移除
动态选主
我们的服务有发布、有扩缩容,原来被选为Token Server的节点可能会下线等,我们采取了基于分布式锁(公平锁)的方式来动态选主。
使用公平锁主要避免独占锁带来的羊群效益。
阈值设置
集群阈值的设置有两种类型:全局阈值和单机均摊
- 全局阈值表示整个集群能承受的总阈值流量,不随节点的变化而变化 例如:全局阈值设置为500,无论该应用部署了多少节点,总的流量阈值保持500不变
- 单机均摊指每个节点能承受的阈值,随着节点的增减Token Server的阈值会动态变化 例如:单机均摊设置为100,3个节点集群流控总阈值为300;扩容了两个节点后,总阈值则为500