服务流量治理策略
- 限流是防御:通过算法与规则控制流量,避免系统崩溃。制请求的速率或数量,防止系统因流量过载而崩溃。其核心目标是 保护系统资源,确保核心功能在高并发下仍能稳定运行;
- 降级是妥协:在资源不足时优先保障核心业务,牺牲次要功能。其核心目标是 丢车保帅;
- 熔断是止损:下游服务不可用或性能恶化时,主动或根据指标切断对下游服务的依赖,防止雪崩效应扩散,核心目标是:快速失败
限流通常是预先设定好的既定策略,但也不是绝对的,比如sentinel的自适应策略可以根据
流量治理组件的特点
- 能够提供最基础的流量控制,如QPS、线程数等;
- 提供多种拒绝策略:
- 如快速失败、排队等待、根据热点参数限流等;
- 根据特定的触发条件,执行降级、熔断;如慢调用次数、CPU利用率达到一定阈值,触发对应的降级;
- 流量控制策略的持久化;策略通常是长期的,不能只是内存存储,每次启动重新配置;通常会使用配置中心来搭配;如Nacos;
- 动态配置和热更新:限流、降级策略需要随时可以修改;
- 非功能性特点:
- 性能;
- 高可用;
- 扩展性;比如规则配置的持久化数据源扩展(Zookeeper、Nacos)、支持的限流场景扩展(HTTP、Dubbo等)
限流的算法及实现
算法 | 算法 | 优缺点 |
---|---|---|
固定窗口计数器 | 统计固定时间窗口(如1秒)内的请求数,超限则拒绝。 | 实现简单,但存在临界时间点突发流量问题(如窗口切换瞬间峰值)。 |
滑动窗口 | 将时间划分为更细粒度的小窗口,动态统计最近N个小窗口的总请求数。 | 缓解固定窗口的临界问题,精度更高,但内存开销较大。 |
漏桶算法 | 以恒定速率处理请求(如水从漏桶流出),超限请求排队或丢弃。 | 平滑流量,避免突发压力,但无法应对合理突发(如冷启动预热)。 |
令牌桶算法 | 系统按固定速率生成令牌,请求需获取令牌才能处理,允许突发流量(桶内令牌积累)。 | 兼顾流量平滑与突发适应,是工业界最常用算法(如Guava RateLimiter)。 |
自适应限流 | 根据系统实时负载(如CPU、延迟)动态调整阈值(如TCP拥塞控制)。 | 灵活应对复杂场景,但实现复杂(如Netflix Adaptive Throttling) |
限流的策略实现及生产应用
1. QPS限流
QPS限流通常使用「固定窗口、滑动窗口」的限流算法实现,QPS、QPM等指标本身也是时间级的统计窗口;
QPS限流通常用于Provider端对外部流量进行限流,用于保护系统;是从提供服务能力的角度进行考虑和限制;
2. 线程数限流
按照线程数限流通常用于系统内部对外部的依赖的调用限制,多用于对依赖的Consumer端的消费限流;
对于外部不稳定的依赖服务,在RT增大的时候,QPS限流并不会有好的效果,此时应该限制内部的线程,防止线程被占用时启动更多的线程,拖垮自身服务。
3. 集群限流
集群限流并不是必须的,他仅需要用在流量在集群内分布不均的情况,因为如果流量分布不均、系统节点的承载能力不同,此时QPS的单机限流就不够精准。
集群限流一般需要一个中心化的TokenServer服务来统一监控流量,发放token,这对TokenServer的性能要求很高,因为要做到限流,就需要在流量到达时,有限请求token,或多或少会增加RT。
4. 匀速限流
匀速限流通常采用漏桶算法,保持恒定的速度让请求通过。这就意味着如果此时有突发流量,超出系统的并发处理能力,那么请求就需要被拒绝或排队等待;通常的做法是排队等待,要等待就必须要有超时时间;
实际上如果采用匀速限流,会有一个现象:未达到QPS,却出现请求失败;
比如限制的QPS=20,超时时间为200ms,假设突然某一时刻20个请求过来,系统并发处理能力为5,处理时长(RT)为100ms,这就出现实际QPS没有超过20,但仍会有10个请求失败,因为同时只能处理5个请求,当处理完10个请求后,剩余的10个请求实际已经等待超时了。
5. warmUp冷启动
对于一些需要额外处理或资源的操作,比如数据库连接,当系统处于低水位时,保持的数据库连接可能很少,此时突发流量来临,建立连接也需要耗时,这是有一些风险的。
当设置warmUp限流,突发流量来到,会将限流阈值设置为1/3,来保护系统,并逐步提高阈值到正常水平。
6. 自适应限流
根据系统的实时负载来自适应的调整限流阈值。这种方式实际使用很少:
- 系统指标映射到对应需要的阈值,这个量化就比较难把控;
- 同一个系统内有多种服务,核心的,非核心的,如何衡量,也很难量化到。