作者 | 赵奕豪

背景

微服务的稳定性一直是开发者非常关注的话题。随着业务从单体架构向分布式架构演进以及部署方式的变化,服务之间的依赖关系变得越来越复杂,业务系统也面临着巨大的高可用挑战。

在生产环境中大家可能遇到过以下不稳定的情况:

  • 大促时瞬间洪峰流量导致系统超出最大负载,load 飙高,系统崩溃导致用户无法下单;

  • “黑马”热点商品击穿缓存,DB 被打垮,挤占正常流量;

  • 调用端被不稳定第三方服务拖垮,线程池被占满,调用堆积,导致整个调用链路卡死。

这些不稳定的场景可能会导致严重后果,但很多时候我们又容易忽视这些与流量/依赖相关的高可用防护。大家可能想问:如何预防这些不稳定因素带来的影响?如何针对流量进行高可用的防护?如何保障服务“稳如磐石”?这时候我们就要请出服务高可用保障的利器 —— Sentinel。

Sentinel 介绍

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

在今年年初,社区宣布了 Sentinel Go 版本的发布,为 Go 语言的微服务提供流控降级、系统自适应保护等特性的原生支持,标志着 Sentinel 朝着多元化与云原生迈出了重要的一步。在这半年的时间内,社区推出了近 10 个版本,逐步对齐了限流、熔断降级、系统自适应流控、热点防护等核心能力;同时社区也在不断扩充开源生态,目前已提供 go-micro、gRPC、Dubbo、Gin 等框架的适配模块,使用这些框架的开发者可以非常简单快速地接入 Sentinel。

Sentinel 里面有两个核心的抽象概念:资源和规则:

  • **资源 (resource) **是 Sentinel 的关键概念,它代表某个逻辑块、函数或接口的调用。它可以是某个 Web API,或者是某个 RPC 服务,甚至是任意的代码块。使用 Sentinel 的 API 将业务逻辑封装起来(或引入 Sentinel 提供的插件),这一步称为“埋点”。每个埋点都有一个资源名称,代表触发了这个资源的调用或访问;

  • **规则 (rule) **即定义到达怎样的条件后进行怎样的控制,针对某个资源或某些资源生效。所有规则都可以动态实时调整,社区提供了 etcd、Consul、Nacos 等动态数据源适配,可以方便地通过这些配置组件来管理规则。

Sentinel 底层通过高性能的滑动窗口进行秒级调用指标统计,结合 token bucket, leaky bucket 和自适应流控算法来透出核心的高可用防护能力。

那么我们如何利用 Sentinel Go 来保证我们微服务的稳定性?下面我们来看几个典型的场景。

高可用防护的核心场景

1. 流量控制

流量是非常随机性的、不可预测的。前一秒可能还风平浪静,后一秒可能就出现流量洪峰了(例如双十一零点的场景)。然而我们系统的容量总是有限的,如果突然而来的流量超过了系统的承受能力,就可能会导致请求处理不过来,堆积的请求处理缓慢,CPU/Load 飙高,最后导致系统崩溃。

因此,我们需要针对这种突发的流量来进行限制,在尽可能处理请求的同时来保障服务不被打垮,这就是流量控制。流量控制的场景是非常通用的,像脉冲流量类的场景都是适用的。

通常在 Web 入口或服务提供方(Service Provider)的场景下,我们需要保护服务提供方自身不被流量洪峰打垮。这时候通常根据服务提供方的服务能力进行流量控制,或针对特定的服务调用方进行限制。我们可以结合前期压测评估核心接口的承受能力,配置 QPS 模式的流控规则,当每秒的请求量超过设定的阈值时,会自动拒绝多余的请求。

下面是最简单的一个 Sentinel 限流规则的配置示例:

_, err = flow.LoadRules([]*flow.FlowRule{{Resource:          "some-service", // 埋点资源名MetricType:        flow.QPS, // QPS 模式Count:             10, // QPS 阈值为 10,即该请求单机每秒不超过 10 次ControlBehavior:   flow.Reject, // 控制效果为直接拒绝,不排队},
})

2. Warm-Up 预热流控

近期发布的 Sentinel Go 0.6.0 版本带来了一种新的流控场景:Warm-Up 预热流控。当系统长期处于低水位的情况下,流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。比如刚启动的服务,数据库连接池可能还未初始化,缓存也处于空的状态,这时候激增的流量非常容易导致服务崩溃。如果采用传统的限流模式,不加以平滑/削峰限制,其实也是有被打挂的风险的(比如一瞬间并发很高)。

针对这种场景,我们就可以利用 Sentinel 的 Warm-Up 流控模式,控制通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,而不是在一瞬间全部放行,同时结合请求间隔控制+排队的控制效果 来防止大量请求都在同一时刻被处理。这样可以给冷系统一个预热的时间,避免冷系统被压垮。

3. 并发控制与熔断降级

一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。

Sentinel Go 提供以下的能力避免慢调用等不稳定因素造成不可用:

  • 并发控制:作为一种轻量级隔离的手段,控制某些调用的并发数(即正在进行的数目),防止过多的慢调用挤占正常的调用;

  • 熔断降级:对不稳定的弱依赖调用进行自动熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。

Sentinel Go 熔断降级特性基于熔断器模式的思想,在服务出现不稳定因素(如响应时间变长,错误率上升)的时候暂时切断服务的调用,等待一段时间再进行尝试。一方面防止给不稳定服务“雪上加霜”,另一方面保护服务的调用方不被拖垮。Sentinel 支持两种熔断策略:基于响应时间(慢调用比例)和基于错误(错误比例/错误数),可以有效地针对各种不稳定的场景进行防护。

注意熔断器模式一般适用于弱依赖调用,即降级后不影响业务主流程,开发者需要设计好降级后的 fallback 逻辑和返回值。另外需要注意的是,即使服务调用方引入了熔断降级机制,我们还是需要在 HTTP 或 RPC 客户端配置请求超时时间,来做一个兜底的防护。

4. 热点防护

流量是随机的,不可预测的。为了防止被大流量打垮,我们通常会对核心接口配置限流规则,但有的场景下配置普通的流控规则是不够的。

我们来看这样一种场景——大促峰值的时候,总是会有不少“热点”商品,这些热点商品的瞬时访问量非常高。一般情况下,我们可以事先预测一波热点商品,并对这些商品信息进行缓存“预热”,以便在出现大量访问时可以快速返回而不会都打到 DB 上。但每次大促都会涌现出一些“黑马”商品,这些“黑马”商品是我们无法事先预测的,没有被预热。

当这些“黑马”商品访问量激增时,大量的请求会击穿缓存,直接打到 DB 层,导致 DB 访问缓慢,挤占正常商品请求的资源池,最后可能会导致系统挂掉。这时候,利用 Sentinel 的热点参数流量控制能力,自动识别热点参数并控制每个热点值的访问 QPS 或并发量,可以有效地防止过“热”的参数访问挤占正常的调用资源。

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

Sentinel Go 提供的 RPC 框架整合模块(如 Dubbo、gRPC)均会自动将 RPC 调用的参数列表附带在埋点中,用户可以直接针对相应的参数位置配置热点流控规则。注意如果需要配置具体值限流,受类型系统限制,目前仅支持基本类型和 string 类型。

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

5. 系统自适应保护

有了以上的流量防护场景,是不是就万事无忧了呢?其实不是的,很多时候我们无法事先就准确评估某个接口的准确容量,甚至无法预知核心接口的流量特征(如是否有脉冲情况),这时候靠事先配置的规则可能无法有效地保护当前服务节点;一些情况下我们可能突然发现机器的 Load 和 CPU usage 等开始飚高,但却没有办法很快的确认到是什么原因造成的,也来不及处理异常。

这个时候我们其实需要做的是快速止损,先通过一些自动化的兜底防护手段,将濒临崩溃的微服务“拉”回来。针对这些情况,Sentinel Go 提供了一种独有的系统自适应保护规则,结合系统指标和服务容量,自适应动态调整流量。

Sentinel 系统自适应保护策略借鉴了 TCP BBR 算法的思想,结合系统的 Load、CPU 使用率以及服务的入口 QPS、响应时间和并发量等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。系统规则可以作为整个服务的一个兜底防护策略,保障服务不挂,对 CPU 密集型的场景会有比较好的效果。同时,社区也在结合自动化控制理论和强化学习等手段,来更好地完善自适应流控的效果和适用场景。

Let’s start hacking!

了解了以上的高可用防护的场景,相信大家对微服务容错与稳定性保障的手段有了新的体会。大家可以动手玩起来,接入 Sentinel Go 来体验这些能力,让微服务“稳如磐石”。

同时 Sentinel 的演进也离不开社区的贡献。Sentinel Go 1.0 GA 版本即将在近期发布,带来更多云原生相关的特性。我们非常欢迎感兴趣的开发者参与贡献,一起来主导未来版本的演进。我们鼓励任何形式的贡献,包括但不限于:

  • bug fix
  • new features/improvements
  • dashboard
  • document/website
  • test cases

开发者可以在 GitHub 上面的 good first issue 列表上挑选感兴趣的 issue 来参与讨论和贡献。我们会重点关注积极参与贡献的开发者,核心贡献者会提名为 Committer,一起主导社区的发展。我们也欢迎大家有任何问题和建议,都可以通过 GitHub issue、Gitter 或钉钉群(群号:30150716)等渠道进行交流。Now start hacking!

  • Sentinel Go repo: https://github.com/alibaba/sentinel-golang

  • 企业用户欢迎进行登记:https://github.com/alibaba/Sentinel/issues/18

  • Sentinel 阿里云企业版:https://ahas.console.aliyun.com/

作者简介

赵奕豪(GitHub: sczyh30),阿里 Sentinel 开源项目负责人,高可用技术布道师。

“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

还在担心服务挂掉?Sentinel Go 让服务稳如磐石相关推荐

  1. 通过Dapr实现一个简单的基于.net的微服务电商系统(十六)——dapr+sentinel中间件实现服务保护...

    dapr目前更新到了1.2版本,在之前4月份的时候来自阿里的开发工程师发起了一个dapr集成Alibaba Sentinel的提案,很快被社区加入到了1.2的里程碑中并且在1.2 release 相关 ...

  2. ESXi 6.7 的https服务挂掉处理方法 503 Service Unavailable (Failed to connect to endpoint: [N7Vmacore4Http16Loc

    ESXi 6.7 的https服务挂掉处理方法 503 Service Unavailable (Failed to connect to endpoint: [N7Vmacore4Http16Loc ...

  3. 还在担心快应用没流量?全场景新玩法来袭!

    2019年3月20日,TEF·2019快应用开发者大会在北京圆满收官落下帷幕.本次大会宣布中国移动终端公司.海信手机加入快应用生态平台,并介绍了快应用生态潜力.快游戏布局.智能场景新玩法.第三方服务战 ...

  4. Alibaba微服务组件Sentinel

    Alibaba微服务组件Sentinel 1.分布式系统遇到的问题 服务的可用性问题 ​ 提供系统可用性的关键是在相关组件失效情况下,系统能多快恢复并继续正确提供服务.当服务器挂掉的时候首先想到什么原 ...

  5. docker没有下载完全_看完此文,妈妈还会担心你docker入不了门?

    上周对象突然心血来潮说想养个小宠物,我问想养啥她又说随便,你看着办!!!这我真的比较难办啊!但是咱们程序员能有个对象就不错了,还不赶紧宠着,我只能照办咯! 我去到了一家宠物店,半天也没有找到合适的目标 ...

  6. java服务限流_SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级

    一.基本简介 1.概念描述 sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性.包括核心的独立类库,监控台,丰富的使用场景验证.(这似乎是阿里开源组件的一贯 ...

  7. mongodump 失败且导致mongo服务挂掉【本质原因,wt文件损坏】

    ====================================================== 标题遇到的问题是我要解决的问题的中间环节. 原本问题是:需要在之前standlone的Mo ...

  8. SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级

    源码地址:GitHub·点这里||GitEE·点这里 一.基本简介 1.概念描述 Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性.包括核心的独立类库,监 ...

  9. 你还在担心开车看不到路标吗?我这这有个路标分类的来玩玩啊(有源码有数据集)

    你还在担心开车看不到路标吗? 别看美女看路标 我这有个路标检测分类的小项目日后成型后肯定可以帮你看清路标哦.(我知道开车不看美女就能看到路标,但我偏偏要放一个美女啊 嘿嘿

最新文章

  1. 大牛告诉你,只有突破程序员思维,才不会沦为码农!
  2. 4道Python装饰器练习题
  3. urlencode python_python爬虫之url中的中文问题
  4. HTML实时显示任务状态,如何监视后台任务进度和完成 (HTML)
  5. struts2关键配置及函数总结,
  6. undefined reference to `boost::system::generic_category()
  7. 设置secureCRT中vim的字体颜色
  8. python echo函数_python如何调用php文件中的函数详解
  9. ffmpeg编解码详细过程
  10. 世界上任何一件事的五个模块
  11. datagrid 重载本地数据_jQuery easyui datagrid重新加载数据
  12. 整理读研期间用过、改进过、写过的代码
  13. 湖南中斯:使用SpreadJS 构建云表单
  14. 利用原生JS将下载链接转换为二维码
  15. 【转】关于测试方面的一些文章
  16. linux服务器如何查看cpu温度,在LINUX下面如何查看CPU的温度
  17. ie 远程控制计算机,通过IE浏览器连接“远程桌面”方法详解
  18. 一个pdf怎么分成两个文件?怎样将一个pdf文件分成几个pdf文件或若干个?
  19. Matplotlib画折线图
  20. python分钟转化为小时_Python将分钟转为小时和分钟

热门文章

  1. 【LXC】 在 LXC 中使用 snap 包管理工具
  2. Python异步爬取知乎热榜
  3. 小区物业费信息管理系统设计c++_律师,我没有签物业合同,可以不交物业费吗?...
  4. wxpython安装_01Python安装教程与特色介绍
  5. 优质 Spring Boot 在线教育平台 源码 免费分享
  6. 如何保护 SpringBoot 配置文件中的敏感信息
  7. 好用到爆的 Java 小技巧
  8. 一文教你 Dubbo 服务性能压测(with JMeter)
  9. org.apache.jasper.JasperException: Unable to compile class for JSP
  10. Lombok 介绍和使用详情