稳定性平台的设计与实现( 四 )


后续工作与思考前面已经提到 , 想要实现「按调用方限流」功能的话 , 需要对我们的服务框架和基础库做一些改造 , 这是我们下一期迭代首先要解决的问题 。
另外一方面 , 就是集群限流功能 。 微服务一向是集群部署的 , 我们谈论的服务 , 默认就是其作为集群对外提供服务的能力 , 而限流设置时切换到单实例视角 , 总是有些别扭之处的 。 前面已提到了集群限流的一些挑战 , 尝试解决这些问题的过程 , 将会是非常有意思的 。 Sentinel 给出了 token server 解决方案 , 我们或许也能提出些不同的思路 。 比如 , 使用常见的基础设施 , 如 redis + Lua 或者 nginx + Lua , 问题的复杂度似乎也能下降不少 。
最后一点思考 , 是关于「限速」与「限额」的 , 它们都被称作 rate limit , 但是实为不同的概念 。 稳定性平台是限速的 , 限制的是速度 , 而速度与时间无关 。 限速时 , 滑动窗口取多长属于实现细节 , 对外界是隐藏的 , 不同的滑动窗口长度 , 影响的是测量精度 , 但「速度」本身才是我们关注的概念 。 而限额不同 , 限额关注的是资源的消耗「量」 。 限额常常也会给出一个时间因素 , 加重了混淆 。 「一分钟请求量不超过 60」 , 并不等价于「QPS 不超过 1」 , 前者是限额 , 后者是限速 。 差不多所有以「XX 时间段内不得超过 YY」的表述 , 都可视为限额 , 而「QPS 不得超过 XX」才是限速 。 它们的区别 , 与高中物理中提到的「速度」vs「平均速度」的区别 , 本质上类似 。 而且 , 「限额」常常由于多条规则来表述 , 比如「一分钟请求不超过 60」且「十分钟请求不超过 500」 , 且「一小时请求不超过 2000」 。 另外 , 「限额」还涉及「限额主体」 , 比如对 IP/user 发起限制 , 不同主体的状态需要保持独立 。
总结一下 , 涉及以下这些点的 , 一般为限额:

  • 对时间段的描述 , 涉及比「秒」更大的单位 , 如「一分钟 xxx」
  • 涉及多条规则 , 如一分钟怎样 , 且一小时怎样
  • 涉及主体 , 如对 IP/user 发起限制
当然前文提到的各种算法 , 如令牌桶、漏桶、滑动窗口等算法都可用来实现限额 。 但由于它们实属不同概念 , 因此稳定性平台是不适用于这些场景的 , 我们需要不同的锤子去锤不同的钉子 。 而且 , 由于限额主体一般来说数量巨大 , 比如 user 可能达到千万甚至亿级别 , 限额的内部状态 , 常常不适合于放在内存中 , 需要借助于外部存储 。
参考文献
  • Release It!: Design and Deploy Production-Ready Software, 对 Circuit Breaker 的介绍见 Chapter 5 Stability
  • CircuitBreaker , Martin Fowler 介绍 Circuit Breaker 的文章
  • Hystrix
  • hystrix-go
  • Leaky bucket, 其中提到了 Leaky Bucket 的不同实现方式
  • How to Design a Scalable Rate Limiting Algorithm
  • 微服务接口限流的设计与思考(附 GitHub 框架源码)
  • Sentinel: 集群流量控制, 介绍了通过 Token Client 和 Token Server 实现集群限流的方案
  • resilience4j, 从中借用了 Registry 的说法
作者:颜发明
【稳定性平台的设计与实现】出处: