分布式环境之高并发场景下的限流与熔断
本文于 364 天之前发表,文中内容可能已经过时。
[^引子]:
限流、熔断、服务降级等等词在现在的互联网公司经常被谈及,进入主题之前先来个段子
1 | 2017年某当红小鲜肉公布恋情,结果微博流量突增好几倍,导致服务挂了,网传当时处理服务异常的工程师正在老家举办婚礼,只好临时先晾下大波客人独自解决问题,求当时工程师的心里阴影面积。 |
看完段子我们来反思一下。(如果是自己的公司我们应该怎么处理这种突增流量呢)
- 如果有足够多的资源,动态扩容可以解决问题,可是必须要先准备大量资源来应对突增的流量成本太高。(不在本文讨论范围内)
- 在有限的资源情况下,限流也能解决这个问题,比如热点数据的限流,系统负载保护。
那什么是限流 ?
以流量为切入点,从流量控制、熔断降级来帮助服务在流量激增的情况下不会直接被压挂。
限流工具对比
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持预热模式、匀速器模式、预热排队模式 | 不支持 | 简单的 Rate Limiter 模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 | 简单的监控查看 | 不提供控制台,可对接其它监控系统 |
为什么选择 Sentinel 点击跳转
项目结构
sentinel-adapter 针对主流框架的适配器,(我主要使用web 与 dubbo)
sentinel-benchmark 基准测试模块
sentinel-cluster 集群限流模块,1.4.0版本正式支持集群限流
sentinel-core 核心模块,所有的限流降级等功能
sentinel-dashboard 控制台模块,提供可视化监控,及规则配置
sentinel-demo 示例模块
sentinel-transport 数据传输模块
先来看看Sentinel的集群限流
我们通常在上生产时会对服务做一个压测,那我们可以根据压测结果来设置限流的值。由于负载均衡策略不同,可能单机处理QPS不同。这时可以采用集群总流量来控制整个QPS。
1 | // web限流 |
Sentinel-dashboard的集群模式想要生效是需要二次开发。
这个是官方建议的架构。我也是按这个架构二次开发。
- dashboard 配置规则
- 将规则持久到Zookeeper
- 所有应用节点监听这个节点
- 数据变更时,应用重新加载规则
以上需要注意的是集群限流还需在集群限流页配置节点信息 也就是指定上面的谁是Server 谁是Client
这里说明一下。官方的架构图稍微有些抽象,我就用大白话说明一下
- token service 这里指的是令牌服务端。有两种方式
- 独立部署一个token server 优点是比较独立。缺点是增加成本,且增加维护的工作量
- 嵌入式 token server 就是以某个应用节点做为token server 其他节点做为client。优点是简单不需要额外成本,缺点与应用耦合在一起。
- client 指的是需要被限流的应用,要指定token server IP 及端口。来获得令牌。
注意: 1.4.0 版本的Sentinel 在集群限流模式下,如果token server 重启后,会出现集群限流失效,变成 了单机限流。原因是token server重启后client重试次数过了后就不会再去重试,转而变成单机模式。【官方回应 1.4.1版本会改成一直重试】
熔断 降级
除了对QPS限流外,我们最常用的就是通过熔断降级保证服务不会完全宕机,例如某个RPC接口处理能力接近瓶颈时,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。
系统负载保护
限流 或者 熔断降级都是指定到具体的请求,而系统负载保护,是针对整体应用集群,当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
主流框架的适配
- web servlet (已经集成)
- dubbo (已经集成)
- spring boot /spring cloud (未测试)
- gRPC (未测试)
- rocketmq (未测试)