阿里面向分布式服务架构的流量控制组件开源了

共 3506字,需浏览 8分钟

 ·

2020-07-03 23:26



作者宿何,阿里巴巴高级开发工程师


Sentinel (https://github.com/alibaba/Sentinel)是阿里巴巴开源的,面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统自适应保护等多个维度来帮助开发者保障微服务的稳定性。Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀、冷启动、消息削峰填谷、集群流量控制、实时熔断下游不可用服务等,是保障微服务高可用的利器,原生支持 Java/Go/C++ 等多种语言,并且提供 Istio/Envoy/SOFA MOSN 全局流控支持来为 Service Mesh 提供高可用防护的能力。



近期,Sentinel Go 0.4.0 (https://github.com/alibaba/sentinel-golang/releases/tag/v0.4.0)正式发布,带来了热点参数流控特性(https://github.com/alibaba/sentinel-golang/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81),可以自动识别统计传入参数中的“热点”参数值并分别进行流控,对于防刷、热点商品访问频次控制等场景非常有用,是高可用流量防护中重要的一环。下面我们来了解一下热点参数流控的场景和原理。


01

热点流量防护介绍



流量是随机的,不可预测的。为了防止被大流量打垮,我们通常会对核心接口配置限流规则,但有的场景下配置普通的流控规则是不够的。我们来看这样一种场景——大促峰值的时候,总是会有不少“热点”商品,这些热点商品的瞬时访问量非常高。一般情况下,我们可以事先预测一波热点商品,并对这些商品信息进行缓存“预热”,以便在出现大量访问时可以快速返回而不会都打到 DB 上。但每次大促都会涌现出一些“黑马”商品,这些“黑马”商品是我们无法事先预测的,没有被预热。当这些“黑马”商品访问量激增时,大量的请求会击穿缓存,直接打到 DB 层,导致 DB 访问缓慢,挤占正常商品请求的资源池,最后可能会导致系统挂掉。这时候,利用 Sentinel 的热点参数流量控制能力,自动识别热点参数并控制每个热点值的访问 QPS 或并发量,可以有效地防止过“热”的参数访问挤占正常的调用资源。


a37b2a96e32b8ad6994b8aa1ba92b4b2.webp


再比如有的场景下我们希望限制每个用户调用某个 API 的频率,将 API 名称+userId 作为埋点资源名显然是不合适的。这时候我们可以在给 API 埋点的时候通过 WithArgs(xxx) 将 userId 作为参数传入到 API 埋点中,然后配置热点规则即可针对每个用户分别限制调用频率;同时,Sentinel 也支持针对某些具体值单独配置限流值,进行精细化流控。


热点参数埋点/规则示例:


// 埋点示例e, b := sentinel.Entry("my-api", sentinel.WithArgs(rand.Uint32()%3000, "sentinel", uuid.New().String()))
// 规则示例_, err = hotspot.LoadRules([]*hotspot.Rule{ { Resource: "my-api", MetricType: hotspot.QPS, // 请求量模式 ControlBehavior: hotspot.Reject, ParamIndex: 0, // 参数索引,0 即为第一个参数 Threshold: 50, // 针对每个热点参数值的阈值 BurstCount: 0, DurationInSec: 1, // 统计窗口时长,这里为 1s SpecificItems: map[hotspot.SpecificValue]int64{ // 支持针对某个具体值单独配置限流值,比如这里针对数值 9 限制请求量=0(不允许通过) {ValKind: hotspot.KindInt, ValStr: "9"}: 0, }, },})


Sentinel Go 提供的 RPC 框架整合模块(如 Dubbo、gRPC)均会自动将 RPC 调用的参数列表附带在埋点中,用户可以直接针对相应的参数位置配置热点流控规则。目前热点规则仅支持基本类型和字符串类型,后续社区会进一步进行完善,支持更多的类型。


Sentinel Go 的热点流量控制基于缓存淘汰机制+令牌桶机制实现。Sentinel 通过淘汰机制(如 LRU、LFU、ARC 策略等)来识别热点参数,通过令牌桶机制来控制每个热点参数的访问量。目前 0.4.0 版本采用 LRU 策略统计热点参数,在后续的版本中社区会引入更多的缓存淘汰机制来适配不同的场景。



02

高可用流量防护最佳实践




在服务提供方(Service Provider)的场景下,我们需要保护服务提供方不被流量洪峰打垮。我们通常根据服务提供方的服务能力进行流量控制,或针对特定的服务调用方进行限制。为了保护服务提供方不被激增的流量拖垮影响稳定性,我们可以结合前期的容量评估,通过 Sentinel 配置 QPS 模式的流控规则,当每秒的请求量超过设定的阈值时,会自动拒绝多余的请求。同时可以结合热点参数流控进行细粒度的流量防护。


在服务调用端(Service Consumer)的场景下,我们需要保护服务调用方不被不稳定的依赖服务拖垮。借助 Sentinel 的信号量隔离策略(并发数流控规则),限制某个服务调用的并发量,防止大量慢调用挤占正常请求的资源;同时,借助熔断降级规则,当异常比率或业务慢调用比例超过某个阈值后将调用自动熔断,直到一段时间过后再尝试恢复。熔断期间我们可以提供默认的处理逻辑(fallback),熔断期间的调用都会返回 fallback 的结果,而不会再去尝试本已非常不稳定的服务。需要注意的是,即使服务调用方引入了熔断降级机制,我们还是需要在 HTTP 或 RPC 客户端配置请求超时时间,来做一个兜底的保护。


e171b625ef981ad9da95c521323b2451.webp


在一些请求突刺的场景中,比如 MQ 客户端消费消息的场景,我们可能不希望将多余的消息直接拒绝(重投),而是让这些过量的消息排队逐步处理。这就是“削峰填谷”的场景。我们可以利用 Sentinel 流控规则中的“匀速+排队等待”控制效果来处理这种场景,以固定的间隔时间让请求通过,超出预设量的请求排队等待。这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会把系统压垮;同时我们也期待系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果,而不是直接拒绝所有多余的请求。


b115b51fc1a49195b2c06fbf3a4512a6.webp


同时 Sentinel Go 还提供 全局维度的系统自适应保护能力(https://github.com/alibaba/sentinel-golang/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E6%B5%81%E6%8E%A7),结合系统的 Load、CPU 使用率以及服务的入口 QPS、响应时间和并发量等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。系统规则可以作为整个服务的一个兜底防护策略,保障服务不挂。


af47a5ab232bd170d5a2a3b69e90791d.webp


03

Let's start hacking!



Sentinel Go 版本正在快速演进中,我们非常欢迎感兴趣的开发者参与贡献,一起来主导未来版本的演进。Sentinel Go 版本的演进离不开社区的贡献。若您有意愿参与贡献,欢迎联系我们加入 Sentinel 贡献小组一起成长(Sentinel 开源讨论钉钉群:30150716)。我们会定期给活跃贡献者寄送小礼品,核心贡献者可以提名为 committer,一起主导社区的演进。同时,也欢迎大家通过 AHAS Sentinel 控制台(点击阅读原文) 来快速体验 Sentinel 的能力。Now let's start hacking!



浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报