扛住阿里双十一高并发流量,Sentinel是怎么作到的?

基本介绍

1 名词解释

  • 服务限流 :当系统资源不够,不足以应对大量请求,对系统按照预设的规则进行流量限制或功能限制java

  • 服务熔断:当调用目标服务的请求和调用大量超时或失败,服务调用方为避免形成长时间的阻塞形成影响其余服务,后续对该服务接口的调用再也不通过进行请求,直接执行本地的默认方法linux

  • 服务降级:为了保证核心业务在大量请求下能正常运行,根据实际业务状况及流量,对部分服务下降优先级,有策略的不处理或用简单的方式处理git

服务降级的实现能够基于人工开关降级(秒杀、电商大促等)和自动检测(超时、失败次数、故障),熔断能够理解为一种服务故障降级处理github

2 为何须要限流降级

系统承载的访问量是有限的,若是不作流量控制,会致使系统资源占满,服务超时,从而全部用户没法使用,经过服务限流控制请求的量,服务降级省掉非核心业务对系统资源的占用,最大化利用系统资源,尽量服务更多用户spring

3 Sentinel 简介


Sentinel: 分布式系统的流量防卫兵,是阿里中间件团队 2018 年 7 月开源的,面向分布式服务架构的轻量级流量控制产品,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护系统服务的稳定性架构

Sentinel 的开源生态:并发

功能特性

1 整体介绍

Sentinel 具备如下特征:app

丰富的应用场景:秒杀限流,消息削峰填谷、集群流量控制、实时熔断下游不可用应用等框架

完备的实时监控:Sentinel 同时提供实时的监控功能。能够在控制台中看到接入应用的单台机器秒级数据,甚至 500 台如下规模的集群的汇总运行状况分布式

普遍的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。只须要引入相应的依赖并进行简单的配置便可快速地接入 Sentinel

完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。能够经过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等


Sentinel 分为两个部分:

控制台(Dashboard) 基于 Spring Boot 开发,打包后能够直接运行,不须要额外的 Tomcat 等应用容器

核心库(Java 客户端) 不依赖任何框架/库,可以运行于全部 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持

2 控制台特性


  • 实时监控 支持自动发现集群机器列表、服务健康状态、服务调用经过/拒绝 QPS、调用耗时、图表统计

  • 规则管理及推送 支持在界面配置流控、降级、热点规则,并实时推送

  • 鉴权 控制台支持自定义鉴权接口,提供基本登陆功能

3 核心库功能特性

(1) 应用流控

针对指定应用实例的流量控制,监控应用流量 QPS 或并发线程数,当达到指定的阈值时对流量进行控制,以免被瞬时的流量高峰冲垮,从而保障应用的高可用性

流量控制的手段包括:

  • 直接拒绝

  • Warm Up,即预热/冷启动方式,让经过的流量缓慢增长,在必定时间内逐渐增长到阈值上限,给冷系统一个预热的时间,避免冷系统被瞬间压垮

  • 匀速排队,严格控制请求经过的间隔时间,让请求以均匀的速度经过

(2) 集群流控

不一样于应用流控根据单个应用实例阈值执行限流检查,集群流控只对整个集群调用总量进行限流,例如如下场景:

  • 限制某个用户调用某个 API 的总 QPS,提供 API 的应用在多个机器上部署了多个实例

  • 由于多个应用实例流量不均匀,致使集群调用总量没有到的状况下某些机器就开始限流

仅靠单机维度去限制的话会没法精确地限制整体流量,经过集群精确地控制整个集群的调用总量,结合单机限流兜底,能够更好地发挥流量控制的效果

(3) 网关流控

Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流

网关流控针对 API 网关的场景定制的限流规则,能够针对不一样 route 或自定义的 API 分组进行限流,支持针对请求中的路径、参数、Header、来源 IP 等进行定制化的限流

(4) 熔断降级

若是调用链路中的某个资源不稳定,最终会致使请求发生堆积,经过熔断降级能在调用链路中某个资源出现不稳定状态时(包括调用超时、异常比例升高、异常数升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而致使级联错误

当资源被降级后,在接下来的降级时间窗口以内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException),通过时间窗口以后,退出熔断,并在下一次资源出现不稳定状态再次自动熔断

(5) 热点参数限流

热点即常常访问的数据,热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流 例如如下场景:

  • 用户 ID 为参数,限制用户对接口的范围 QPS

  • 商品 ID 为参数,限制商品下单接口频率

(6) 系统自适应限流

为了解决传统方案:基于操做系统负载(load1,linux 下用 uptime 查看)作进行自适应限流,带来的存在延时、系统性能恢复慢的问题,Sentinel 采用新的思路:根据系统可以处理的请求,和容许进来的请求,来作平衡,而不是根据一个间接的指标(系统 load)来作限流

目标在于:在系统不被拖垮的状况下,尽量提升系统的吞吐率,而不是 负载 必定要到低于某个阈值

系统保护规则是从应用级别的入口流量进行控制,从单台机器的整体 Load、RT、入口 QPS 和线程数四个维度监控应用数据,当实际运行达到限定阈值进行限流保护,支持的阈值类型:

  • Load:当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统时间运行监测到的的 maxQps * minRt (最小响应时间)计算得出

  • RT:当单台机器上全部入口流量的平均 RT(响应时间)

  • 线程数:当单台机器上全部入口流量的并发线程数

  • 入口 QPS:当单台机器上全部入口流量的 QPS

(7) 黑白名单控制

Sentinel 黑白名单根据资源的请求来源(origin)限制资源是否经过,若配置白名单则只有请求来源位于白名单内时才可经过;若配置黑名单则请求来源位于黑名单时不经过,其他的请求经过

快速入门

1 安装控制台

从 github release 页面(https://github.com/alibaba/Sentinel/releases)下载最新控制台 jar 包

命令行启动控制台:

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

2 应用接入 Sentinel

Sentinel 适配了常见主流框架,包括 Dubbo、Spring Boot、Spring WebFlux、gRPC、Zuul、Spring Cloud Gateway、RocketMQ、Web Servlet,对于须要限流的资源,支持用原生 Java 的 try-catch 接入或者使用注解

下面以常见的 Spring Boot 注解的方式做为示例:引入 sentinel 适配 Spring Cloud 的依赖:

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>

application.yml 指定控制台地址:

spring:
 cloud:
   sentinel:
     transport:
       dashboard: IP:端口号

定义须要限流的资源:

@RestController
public class TestController {

   @GetMapping(value = "/hello")
   // 定义须要限流的资源名称为hello
   @SentinelResource("hello")
   public String hello() {
       return "Hello Sentinel";
   }
}

请求一次上面的 http hello 接口后,触发 Sentinel 客户端初始化,才能在控制台看到接口

添加流控规则:

频繁请求接口,能够看到部分请求被拒绝:

注意:上面的配置方式是没有作持久化的,生产环境不建议使用

3 规则配置

Sentinel 提供 动态规则数据源 支持来动态地管理、读取配置的规则。Sentinel 提供的 ReadableDataSource 和 WritableDataSource 接口简单易用,很是方便使用。

Sentinel 动态规则源针对常见的配置中心和远程存储进行适配,目前已支持 Nacos、ZooKeeper、Apollo、Redis 等多种动态规则源,能够覆盖到不少的生产场景

实现原理

下面介绍 Sentinel 客户端基本原理

1 基本概念

  • Resource 资源 Sentinel 中,须要被流量保护的方法、代码块均可以称为资源,每一个资源都须要定义一个惟一的资源名词,用于匹配相关规则

  • Entry Sentinel 功能入口类,Entry 能够经过对主流框架的适配自动建立,也能够经过注解的方式或调用 SphU API 显式建立,建立后执行资源和规则匹配和校验

  • Slot 功能插槽,由 Enty 类建立,每一个资源对应一系列 Slot,Slot 实现资源信息收集、规则匹配、校验的,多个 Slot 经过组成 Slot Chain,在进入资源和退出资源时分别基于责任链模式调用 entry()和 exit()方法

2 工做原理

一个简单的 demo:

String resourceName = "resourceName";
Entry entry = null;
try {
entry = SphU.entry(resourceName);
System.out.println("resource running");
} catch (BlockException e) {
// 限流
throw e;
} catch (Throwable e) {
e.printStackTrace();
throw e;
} finally {
if (entry != null) {
entry.exit();
}
}

主要流程以下:

  • 进入资源方法以前,基于 SphU 建立 Entry,Entry 获取查找资源关联的 Slot Chain 信息,若是找不到则建立,并基于责任链模式调用 Slot 的 entry()方法

  • 资源方法调用

  • 资源方法调用完成后,经过 Entry 触发 Slot 的 exit()逻辑

框架比较

Sentinel Hystrix resilience4j
隔离策略 信号量隔离(并发线程数限流) 线程池隔离/信号量隔离 信号量隔离
熔断降级策略 基于响应时间、异常比率、异常数 基于异常比率 基于异常比率、响应时间
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于 RxJava) Ring Bit Buffer
动态规则配置 支持多种数据源 支持多种数据源 有限支持
扩展性 多个扩展点 插件的形式 接口的形式
基于注解的支持 支持 支持 支持
限流 基于 QPS,支持基于调用关系的限流 有限的支持 Rate Limiter
流量整形 支持预热模式、匀速器模式、预热排队模式 不支持 简单的 Rate Limiter 模式
系统自适应保护 支持 不支持 不支持
控制台 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 简单的监控查看 不提供控制台,可对接其它监控系统

值得补充的是:相比 Hystrix 基于线程池隔离进行限流,这种方案虽然隔离性比较好,可是代价就是线程数目太多,线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。

Sentinel 并发线程数限流不负责建立和管理线程池,而是简单统计当前请求上下文的线程数目,若是超出阈值,新的请求会被当即拒绝,效果相似于信号量隔离

相关文章
相关标签/搜索