一、背景
电商目前发展的阶段,有很多秒杀抢购场景,会带来瞬时巨大的流量,瞬时大流量会造成服务的不稳定。
场景一:
目前应对的方案通常是在流量入口处基于路径、集群、服务名、接口方法名,或是集群维度、单实例维度去做限流(参考 ——限流管理),诚然通过配置入口处的服务限流可以在秒杀场景挡住瞬时大流量带来的冲击。
- 入口限流分为本地限流和中心化限流(分布式限流),本地限流方式五花八门,业内比较知名的有阿里的sentinel 。但是一些低流量场景,通过本地限流的方式在准确性上存在较大的不足,此时需要借助分布式限流方式来保护链路稳定性。
本地限流 | 分布式限流 | |
---|---|---|
优点 | 维护简单,性能高,无网络请求。 | 限流精准,特别适合小流量场景。 |
缺点 | 1. 根据业务流量倾向程度,误差不可控;2. 对小流量场景不友好。 | 1. 会额外产生网络请求、对接口时延有劣化(10ms~);2. 如果qps过大,redis会有热key问题;正常情况,单key流量适合一万qps之内(可以通过设计token-pool或者分片key来缓解)。 |
场景二:
即使入口处和基础组件处的限流管理都做好了,这样的限流在秒杀等瞬时流量场景,限流依然是有损的。秒杀商品通常单价低、gmv贡献少、资源要求多、秒杀抢购会抢占普通商品的流量,需要针对热点流量单独做区分限流。
目前在电商交易和库存,都针对单品秒杀场景做了个性化的****限流,方案如下,如下两个方案都已上线
-
交易下单:
-
库存扣减:
在个性化限流的实现上,业务团队(交易、库存)有一些共性问题和痛点:
-
都依赖一些现有的组件来各自实现一套,公司现有组件不好用(iesarch/simple_rate_limit),都需要自己定制一些功能,或者重新实现一些功能;
-
都依赖开源项目alibaba/sentinel,认为其策略比较完善。但某些场景还不够用,例如 sentinel 缺乏全局分布式限流之间的协同。
-
都有一些个性化的场景:
二、问题域分析
当前需要重点解决的问题的问题域分析。
未来会面临的问题分析(结合具体情况,可以偏中短期,也可以偏长期)。
目前电商已经有2w+的L0&L1核心链路入口限流配置,在接口覆盖率上已达到90%+;但同时需要对限流准确性,配置合理性进行治理。
除了接口限流外,电商还有很多的热点链路,需要做服务内个性化限流。如交易中心-热点直播间、热点商品等提单下单链路限流等 ;这部分长期需要和稳定性poc联合,如何有效结合人工&自动化方式发掘一个个热点链路,做到对电商内的风险的预防、核心链路的保护。
【基础组件专项】目前基础组件的自适应限流能力差,无法有效起到对基础组件的保护作用。以mysql的热点问题为例,缺少热点事前提前发现、事中限流保护能力 。
总结:分布式限流是三个问题域中核心的基础能力。
三、名词解释
名词 | 解释 |
---|---|
本地限流 | 只依赖 单机的逻辑,没有全局的聚合;可以分为 集群限流和单机限流(这里的集群限流,本质还是单机限流) |
分布式限流 | 依赖中心化的存储-redis,做全局聚合; |
热key限流 | 每个resource下的每个热key都单独限定一个的qps阈值; |
warm-up | 请求预热,预热/冷启动,限流阈值缓慢上升; |
token-pool | 本地存储token,用来解决redis的热key问题; |
四、现有限流组件对比
五、底层限流策略
Limiter-SDK能力视角
限流数据结构主要有:固定窗口、滑动窗口、漏桶、令牌桶等;原理详细见:bytedance.feishu.cn/wiki/wikcnO…
具体可分为本地限流 & 分布式限流:
5.1 分布式限流
红色部分代表二期实现
5.2 本地限流
本地单机限流上述策略 集成了sentinel的sdk,一期全部实现;
单机限流以上能力,全部集成;
六、架构设计
6.1 系统架构图
主要模块有:
核心域
-
主要对外暴露的接口为三类:
- 通用限流IsLimit(); 2. 分布式限流IsGlobalLimit(); 3.本地限流IsLocalLimit();
-
分层设计:依赖底层原子限流策略,上层根据不同的场景来组装;底层策略为(文档第五节)提到的限流策略的实现类;
通用限流默认使用分布式限流,同时包含一个熔断器。如果分布式限流报错过高,会自动降级到本地限流。如果过一段时间恢复后,再次切换到分布式限流。
本地token池-step机制
-
高qps场景下(单key>1万),增加本地token池,优先判断本地token池,再判断中心redis集群
-
增加每次从redis集群获取token数,并放入本地token池,减轻对redis集群的负载
-
多获取的token,放在本地token池中,留给当前限流周期请求使用。
分为同步和异步二种方案,一期选择同步方案(精度更高);
- 同步:时延较高,不会漏限:√
- 异步~~~~:时延低,漏限严重
支持自动计算step
简单的说,就是会实时统计每个实例的每次并发请求阻塞量,动态计算对应的step,从而加锁一次请求redis(获取多个token数),来极大的减轻对redis的压力,从而支撑10万+的qps。
配置域
集群限流配置:conf-key:psm
“上游PSM+Cluster+调用Method+本服务Cluster”粒度配置限流阈值
注:下面的cluster-conf中source_conf的psm、cluster支持*,代表全部的上游psm以及集群都配置
自定义Key限流配置:conf-key:psm
总结:上述大部分的策略配置都不需要关心,业务需要关注的极简配置参数如下:
滑动窗口固定窗口 | 固定阈值流控(default) | warm-up动态阈值限流 | 热key限流 |
---|---|---|---|
初始化公共的参数 | redis_psm、数据统计类型(滑窗or固窗)、降级配置 | ||
不同策略需要的参数 | 阈值、限流Key | 阈值、限流Key、warm-up(预热时长、冷却因子) | 阈值、限流Key、热key-阈值map集 |
外部依赖域
主要有三个外部依赖:
-
分布式限流所依赖的热点检测sdk;
-
分布式限流需要的中心化Token存储-redis;
-
本地限流需要的集成的sentinel组件;
6.2 系统流程图
6.3 监控&报警
- 监控指标
限流稳定性、接口限流前后qps、接口时延、熔断器监控等
- 报警指标
错误率、是否达到限流值、是否降级到本地限流
6.4 容灾设计
分布式限流故障,支持自动&手动降级到本地限流;熔断器有三种状态:
Closed 状态:也是初始状态,该状态下,熔断器会保持闭合,对资源的访问直接通过熔断器的检查。
Open 状态:断开状态,熔断器处于开启状态,对资源的访问会被切断。
Half-Open 状态:半开状态,该状态下除了探测流量,其余对资源的访问也会被切断。探测流量指熔断器处于半开状态时,会周期性的允许一定数目的探测请求通过,如果探测请求能够正常的返回,代表探测成功,此时熔断器会重置状态到 Closed 状态,结束熔断;如果探测失败,则回滚到 Open 状态。
这三种状态之间的转换关系这里做一个更加清晰的解释:
初始状态下,熔断器处于 Closed 状态。如果基于熔断器的统计数据表明当前资源触发了设定的阈值,那么熔断器会切换状态到 Open 状态;
Open 状态即代表熔断状态,所有请求都会直接被拒绝。熔断器规则中会配置一个熔断超时重试的时间,经过熔断超时重试时长后熔断器会将状态置为 Half-Open 状态,从而进行探测机制;
处于 Half-Open 状态的熔断器会周期性去做探测。
七、测试文档
八、总结&规划
8.1 总结
Limiter的能力地图分为自定义key限流&集群限流:
技术优势:
稳定性:整体sdk接口成功率大于99.99%,接口时延P99低于20ms;
准确性:sdk默认接口限流准确率>=95%;
高性能:本地限流原理上支持水平扩展,能够支持十万以至于百万级qps,但是会存在一定误差;全局限流准确性高,但通常由于redis的热key限制,只能够支持万级别的qps,本方案能支持极高qps场景分布式限流能力(10万+的qps);
鲁棒性:自动(手动)降级:全局限流接口错误率上升,支持自动(手动)降级到本地限流逻辑;
丰富的限流组件功能、策略,能力对标alibaba/sentinel
8.2 规划
sdk能力丰富:
限流的时间维度扩展限流维度到(分钟、小时、天、月);
支持单元化的建设,完成单元化改造。
集成并发量限流能力到目前的架构;
平台影响力提升:
完成商品、交易等核心业务接入;
对齐Neptune底层分布式限流能力;推动Neptune底层的分布式限流迁移到Limiter;
联合电商SRE对接最新的分布式限流的配置、监控、治理、预案;为b端小流量场景稳定性治理赋能;
联合服务架构稳定性poc,进行热点链路的人工&自动方式识别,限流保护。