Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景java
本文介绍阿里开源限流熔断方案Sentinel功能、原理、架构、快速入门以及相关框架比较linux
服务限流 :当系统资源不够,不足以应对大量请求,对系统按照预设的规则进行流量限制或功能限制git
服务熔断:当调用目标服务的请求和调用大量超时或失败,服务调用方为避免形成长时间的阻塞形成影响其余服务,后续对该服务接口的调用再也不通过进行请求,直接执行本地的默认方法github
服务降级:为了保证核心业务在大量请求下能正常运行,根据实际业务状况及流量,对部分服务下降优先级,有策略的不处理或用简单的方式处理spring
服务降级的实现能够基于人工开关降级(秒杀、电商大促等)和自动检测(超时、失败次数、故障),熔断能够理解为一种服务故障降级处理架构
系统承载的访问量是有限的,若是不作流量控制,会致使系统资源占满,服务超时,从而全部用户没法使用,经过服务限流控制请求的量,服务降级省掉非核心业务对系统资源的占用,最大化利用系统资源,尽量服务更多用户并发
Sentinel: 分布式系统的流量防卫兵,是阿里中间件团队2018年7月开源的,面向分布式服务架构的轻量级流量控制产品,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护系统服务的稳定性app
Sentinel 的开源生态:框架
Sentinel 具备如下特征:分布式
丰富的应用场景:秒杀限流,消息削峰填谷、集群流量控制、实时熔断下游不可用应用等
完备的实时监控:Sentinel 同时提供实时的监控功能。能够在控制台中看到接入应用的单台机器秒级数据,甚至 500 台如下规模的集群的汇总运行状况
普遍的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。只须要引入相应的依赖并进行简单的配置便可快速地接入 Sentinel
完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。能够经过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等
Sentinel 分为两个部分:
控制台(Dashboard) 基于 Spring Boot 开发,打包后能够直接运行,不须要额外的 Tomcat 等应用容器
核心库(Java 客户端) 不依赖任何框架/库,可以运行于全部 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持
实时监控
支持自动发现集群机器列表、服务健康状态、服务调用经过/拒绝QPS、调用耗时、图表统计
规则管理及推送
支持在界面配置流控、降级、热点规则,并实时推送
鉴权
控制台支持自定义鉴权接口,提供基本登陆功能
针对指定应用实例的流量控制,监控应用流量QPS或并发线程数,当达到指定的阈值时对流量进行控制,以免被瞬时的流量高峰冲垮,从而保障应用的高可用性
流量控制的手段包括:
不一样于应用流控根据单个应用实例阈值执行限流检查,集群流控只对整个集群调用总量进行限流,例如如下场景:
仅靠单机维度去限制的话会没法精确地限制整体流量,经过集群精确地控制整个集群的调用总量,结合单机限流兜底,能够更好地发挥流量控制的效果
Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流
网关流控针对 API网关的场景定制的限流规则,能够针对不一样 route 或自定义的 API 分组进行限流,支持针对请求中的路径、参数、Header、来源 IP 等进行定制化的限流
若是调用链路中的某个资源不稳定,最终会致使请求发生堆积,经过熔断降级能在调用链路中某个资源出现不稳定状态时(包括调用超时、异常比例升高、异常数升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而致使级联错误
当资源被降级后,在接下来的降级时间窗口以内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException),通过时间窗口以后,退出熔断,并在下一次资源出现不稳定状态再次自动熔断
热点即常常访问的数据,热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流
例如如下场景:
为了解决传统方案:基于操做系统负载(load1,linux下用uptime查看)作进行自适应限流,带来的存在延时、系统性能恢复慢的问题,Sentinel采用新的思路:根据系统可以处理的请求,和容许进来的请求,来作平衡,而不是根据一个间接的指标(系统 load)来作限流
目标在于:在系统不被拖垮的状况下,尽量提升系统的吞吐率,而不是 负载 必定要到低于某个阈值
系统保护规则是从应用级别的入口流量进行控制,从单台机器的整体 Load、RT、入口 QPS 和线程数四个维度监控应用数据,当实际运行达到限定阈值进行限流保护,支持的阈值类型:
Sentinel黑白名单根据资源的请求来源(origin)限制资源是否经过,若配置白名单则只有请求来源位于白名单内时才可经过;若配置黑名单则请求来源位于黑名单时不经过,其他的请求经过
从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
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客户端初始化,才能在控制台看到接口
添加流控规则:
频繁请求接口,能够看到部分请求被拒绝:
注意:上面的配置方式是没有作持久化的,生产环境不建议使用
Sentinel 提供 动态规则数据源 支持来动态地管理、读取配置的规则。Sentinel 提供的 ReadableDataSource 和 WritableDataSource 接口简单易用,很是方便使用。
Sentinel 动态规则源针对常见的配置中心和远程存储进行适配,目前已支持 Nacos、ZooKeeper、Apollo、Redis 等多种动态规则源,能够覆盖到不少的生产场景
下面介绍Sentinel客户端基本原理
Resource 资源
Sentinel中,须要被流量保护的方法、代码块均可以称为资源,每一个资源都须要定义一个惟一的资源名词,用于匹配相关规则
Entry
Sentinel功能入口类,Entry 能够经过对主流框架的适配自动建立,也能够经过注解的方式或调用 SphU API 显式建立,建立后执行资源和规则匹配和校验
Slot
功能插槽,由Enty类建立,每一个资源对应一系列Slot,Slot实现资源信息收集、规则匹配、校验的,多个Slot经过组成Slot Chain,在进入资源和退出资源时分别基于责任链模式调用entry()和exit()方法
一个简单的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(); } }
主要流程以下:
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持预热模式、匀速器模式、预热排队模式 | 不支持 | 简单的 Rate Limiter 模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 | 简单的监控查看 | 不提供控制台,可对接其它监控系统 |
值得补充的是:相比Hystrix基于线程池隔离进行限流,这种方案虽然隔离性比较好,可是代价就是线程数目太多,线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。
Sentinel 并发线程数限流不负责建立和管理线程池,而是简单统计当前请求上下文的线程数目,若是超出阈值,新的请求会被当即拒绝,效果相似于信号量隔离
《Sentinel官方文档》
https://github.com/alibaba/Sentinel/wiki
《从 Hystrix 迁移到 Sentinel》
https://github.com/alibaba/Sentinel/wiki/Guideline:-从-Hystrix-迁移到-Sentinel