Sentinel—高可用流量管理框架/服务容错组件
一.为什么要用Sentinel?
1.微服务架构中当某服务挂掉的时候常见的原因有哪些?
1.异常没处理
比如DB连接失败,文件读取失败等
2.突然的流量激增
比如:用户经常会在京东、淘宝、天猫、拼多多等平台上参与商品的秒杀、限时抢购等优惠活动,也会在节假日使用12306 抢火车票、高铁票,甚至有时候还要帮助同事、朋友为他们家小孩拉投票、刷票,这些场景都无一例外的会引起服务器流量的暴涨,导致网页无法显示、APP反应慢、功能无法正常运转,甚至会引起整个网站的崩溃(服务雪崩)。
3.被其它服务拖垮
在微服务项目中,经常存在服务A调用服务B,服务B又调用服务C等微服务级联调用的场景,当服务C出现故障,服务B和服务A都会跟着出现故障,因为它们之间存在调用链关系;有时候调用链会很长并且很复杂,比如服务A不仅调用了服务B,还调用了服务H、服务I、服务J等等,同时服务A调用链的最长链条终端有可能是从服务C、服务D一直到服务Z,这种调用复杂的调用链条一旦出现故障,有可能直接让整个微服务体系都无法提供服务,造成的影响是致命的。这种由于调用链中某一个节点出现故障而引发的级联故障,称为服务雪崩,也称为级联故障、级联失效。
2.容错机制
异常没处理,我们处理一下异常就可以,而对于另外两个原因导致的服务雪崩,我们应该怎么解决呢或者说应该怎么建立容错机制呢?
常见的容错机制有隔离、超时、限流、熔断、降级等。
隔离
它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的 系统服务。常见的隔离方式有:线程池隔离和信号量隔离。
超时
在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应, 就断开请求,释放掉线程。
限流
限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到 的需要限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。
熔断
在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。
降级
降级其实就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。
3.常见的容错组件
Hystrix
Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
Resilience4J
Resilicence4J一款非常轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是Hystrix官方推荐的替代产品。不仅如此,Resilicence4j还原生支持Spring Boot 1.x/2.x,而且监控也支持和prometheus等多款主流产品进行整合。
Sentinel
Sentinel 是阿里巴巴开源的一款断路器实现,是面向分布式服务架构的轻量级流量控制产品,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保护服务的稳定性。本身在阿里内部已经被大规模采用,比如双11高流量场景,非常稳定。
比如:我们可以通过Sentinel,为秒杀、抢购、抢票、拉票等功能提供API接口层面的流量限制,让突然暴涨而来的用户访问受到统一的管控,使用合理的流量放行规则使得用户都能正常得到服务。同时可以解决应用雪崩效应引发的一系列问题。
三者对比:

二.Sentinel是什么?
1.Sentinel 定义
Sentinel 是面向分布式服务架构的轻量级流量控制产品,是高可用防护组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保护服务的稳定性。
2.Sentinel的功能
2.1流量控制
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。因为任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:

2.2 熔断降级
1.什么是熔断降级?
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。
2.熔断降级设计理念
Sentinel采取了两种手段:
方式1:通过并发线程数进行限制:
Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
方式2:通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
2.3 系统负载保护
Sentinel 同时对系统的维度提供保护。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
3.Sentinel的特点
丰富的应用场景:
Sentinel承接了阿里巴巴多年的双十一大促高流量的核心场景,例如秒杀,消息削峰填谷,实时熔断下游不可用应用等.
完备的实时监控:
Sentinel同时提供实时的监控功能,可以在控制台看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
广泛的开源生态:
Sentinel提供开箱即用的与其它开源框架的整合模块,例如与Spring Cloud,Dubbo,gRPC的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
完善的SPI扩展点:
Sentinel提供简单易用,完善的SPI扩展点。可以通过实现扩展点,快速地定制逻辑。例如定制规则管理,适配数据源等。
4.Sentinel 基本概念
4.1资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
4.2规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
三.Sentinel的快速使用
1.Sentinel的组成部分
核心库(Java客户端):不依赖任何框架/库,能够运行于所有Java运行环境中,同时对SpringCloud/Dubbo等框架也有较好的支持
控制台(Dashboard):基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。
2.如何启动Dashboard
2.1 查询跟当前使用的SpringCloud兼容的版本

2.2下载dashboard的jar包
地址: https://github.com/alibaba/Sentinel/releases/tag/v1.8.0
放入指定目录:比如java项目的工作空间。
2.3 启动Dashboard的两种方式
方式1:
默认端口号是8080
java -jar D:/idea_workspace/sentinel-dashboard-1.8.0.jar

方式2:
可以自己设置端口号
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080-Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:/idea_workspace/sentinel-dashboard-1.8.0.jar
2.4 访问
http://localhost:8080
默认用户名和密码都是sentinel


此时没有关联的微服务
3.微服务中集成Sentinel
3.1 添加sentinel包
在需要限流的上游服务(调用方)中加入jar包
这里在案例Users服务中添加
<!-- 导入sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

3.2 添加配置信息

重启服务Users
3.3 Sentinel懒加载
此时刷新Dashboard,看不到服务信息。这是因为默认情况下Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。也就是Sentinel设置了懒加载,解决方法有两种:
方法1:先运行一下Users服务
方法2:配置spring.cloud.sentinel.eager=true ,取消Sentinel控制台懒加载。
再次刷新,可以看到:

3.4 测试使用
我们先简单测试一下Sentinel的流控功能,在设置之前,可以任意刷新Users服务中接口次数。
假设这里设置Users服务下的goods接口1秒钟内只能刷新两次:



再次刷新Users服务中的goods接口:
当QPS超过2次以后,会出现被限流的提示:

3.5 怎么移除不需要监控的服务

四.Sentinel的规则
1.流控规则
1.1流控规则有哪些?
流量控制有以下几个角度:
资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
运行指标,例如 QPS(每秒查询率)、线程池、系统负载等;
控制的效果,例如直接限流、冷启动、排队等。
Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

资源名:
唯一的资源名称,默认是接口路径,也可以自定义.
针对来源:
指定对哪个微服务进行限流,这里填写服务名,默认是default,表示不区分来源。
阈值类型:
QPS: 每秒请求数,当调用当前接口的每秒请求数达到阈值,则限流
线程数:当调用当前接口的线程数达到阈值,则限流。
流控模式:
**直接:**当前资源达到限流条件时,开启限流。
关联: 当关联的资源达到限流条件时,开启限流.
例如存在资源 A和B,A资源依赖B资源,当B资源达到阈值,则限流A。
比如支付模块B达到阈值,则限流订单模块A,因为支付已经达到上限了,过量的订单会使得支付压力更大,需要限流。
**链路:**只针对从指定链路访问到本资源的请求做统计,判断是否达到限流条件时,开启限流.
例如有两条请求链路:
/query /queryUsers
/save /queryUsers
如果只限制从/query进入到/queryUsers的请求,就可以设置链路模式.
流控效果
快速失败
预热Warm UP
排队等待
1.2流控模式
1.直接模式
上面已演示
2 关联模式的使用
1.添加测试代码

2.添加流控规则
当关联资源/pay的阈值达到3时,资源/addOrder被流控

3.模拟关联资源/pay超过阈值


启动
4.测试结果
/test1被流控

3链路模式的使用
1.添加测试代码


Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法,需要利用@SentinelResource注解。
2.添加流控规则
对从/query路径调用users资源(也就是queryUsers方法)进行流控,这里为了方便测试,阈值设置为1

3.设置关闭context整合
如果直接测试上述规则,会发现没有作用,这是因为自从 sentinel-spring-webmvc-adapter -1.7.2 开始,在SentinelWebMvcConfig对象(sentinel参数配置类)中含有一个webContextUnify属性,默认值为true,表示合并web context,达到节约内存的目的;如果设置为false,表示入口处的contexts会拆分为不同的url。我们针对链路模式,必须设置为false,否则会导致链路模式不生效。

4.测试
启动服务测试:
当一秒内访问超过1次,就报错.

后续我们会对此做降级处理,而不是只是返回异常。
1.3 流控效果
1.快速失败
就是被限流时,返回失败信息到页面

2.预热Warm UP
默认coldFactor冷加载因子为3,即请求QPS从(请求总数/3)开始,经过我们设置的时间才逐渐升至设定的QPS阈值。
例如:阈值为10,预热时长设置为4秒

限流效果:系统初始化的阈值为10/3等于3.即阈值刚开始为3.如果刚开始每秒请求数大于3则默认失败。过了4秒后阈值才慢慢升高恢复到10,即4秒后能承受大于3但是仍要小于10的请求,才不会被限流
应用场景
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
3.排队等待
让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的排队等待。他还会设置一个超时时间,当请求超过超时时间还未处理,则会被丢弃.
注意:
阈值类型必须设置为QPS,否则无效
匀速排队模式暂时不支持 QPS > 1000 的场景。
例如:对资源/goods设置每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒。

测试:



应用场景:
这种方式主要用于处理间隔性突发的流量,例如消息队列。在某一秒有大量的请求到来,而接下来的几秒则可能处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,以起到“削峰填谷”的效果,而不是拒绝所有请求。
2.降级规则
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断
1.慢调用比例
熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。
选择以慢调用比例作为阈值,需要设置允许的慢调用RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长内请求数目大于设置的最小请求数目,并且慢调用比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断,若大于设置的慢调用RT则会再次被熔断.
例如:以下配置的含义为:如果1秒内持续进入大于等于5个请求,并且请求响应的时间大于1000ms时,这个请求即为慢调用,当慢调用的比例大于0.5时会触发降级,熔断时间为5秒。

测试:
添加测试代码:

Jmeter中模拟多个慢应用并运行

再浏览器中访问test接口时,会被降级

2.异常比列
如果1秒内持续进入大于等于最小请求数,并且请求出现异常的比例超过比例阈值时,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断
例如:如下配置为:如果1秒内持续进入大于等于5个请求,并且请求出现异常的比例超过0.5时,会触发降级

测试代码:
添加代码,模拟出异常情况

Jmeter中模拟多个慢应用并运行

浏览器中访问test2接口

3.异常数
如果1秒内持续进入大于等于最小请求数,并且请求出现异常的次数超过设置的异常数时,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断,若大于设置的慢调用RT则会再次被熔断.

触发熔断后的处理措施:
1.提供fallback实现服务降级
2.读缓存(DB访问降级)
3.返回错误result
3.热点参数流控规则
1.1什么是热点参数流控
热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。
热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
1.2 测试
添加测试代码:

添加规则:
对资源getGoodsById中的第一个参数整体限流10,但对其中的id=1的值限流3.


4.系统规则
当容量评估不到位,某个大流量接口限流配置不合理或者没有配置,导致系统崩溃,或者突然发现机器的load和CPU等开始飙升,但不能快速确认是什么原因造成等,这时候,需要一个全局的兜底防护方案,即使缺乏容量评估也能有一定的保护机制。这就是系统保护规则。
Sentinel系统自适应限流从整体维度对应入口流量进行控制,结合应用的Load、cup使用率、总体平均RT、入口QPS和并发线数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

load自适应(仅对Linux/Unix系统有效)
当系统load1(1分钟平均负载)超过阈值,且并发线程数超过系统容量时触发。其中的load1,可以在Linux系统上通过命令 uptime 查看,这个命令返回3个值,分别为load1、load5、load15,表示系统1分钟的平均负载、5分钟的平均负载、15分钟的平均负载。
CPU usage(1.5.0+ 版本): 当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT: 当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数: 当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS: 当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
五.统一异常处理—BlockException
在上述规则测试中,当违反规则时,出来的异常信息页面不够友好和统一,我们可以通过设置统一的异常处理类,针对不同规则显示不同异常信息。
创建一个配置类,实现BlockExceptionHandler接口
/**
* author:呆萌老师
* qq:2398779723 微信: it_daimeng
*/
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
ResponseResult rs=null;
if(e instanceof FlowException)
rs= Response.createFailResp(-1,"接口限流了");
else if(e instanceof DegradeException)
rs=Response.createFailResp(-2,"服务降级了");
else if(e instanceof ParamFlowException)
rs=Response.createFailResp(-3,"参数限流了");
else if(e instanceof AuthorityException)
rs=Response.createFailResp(-4,"权限规则不通过");
else if(e instanceof SystemBlockException)
rs=Response.createFailResp(-5,"系统保护");
httpServletResponse.setContentType("application/json;charset=utf-8");
httpServletResponse.getWriter().write(JSON.toJSONString(rs));
}
}
添加规则测试:

六 @SentinelResource注解详解
通过前面的学习,我们了解到通过Sentinel除了可以控制对Spring Mvc接口层级的控制,也可以对service层的某个方法控制,也就是说在我们实际项目开发时不仅仅限于接口,可能对于某个方法的调用限流,对于某个外部资源的调用限流等都希望做到控制。
那么如何使用@SentinelResource注解灵活的定义控制资源以及如何配置控制策略。我们来系统学习一下。
1.自定义资源点

我们可以对这个资源点做限流处理
2 实现异常处理
默认情况下,Sentinel对控制资源的限流处理是直接抛出异常。设置了统一异常处理BlockExceptionHandler也会发现对非控制层的资源没有用,这样对用户交流不友好,我们需要处理一下@SentinelResource资源的异常信息。
@SentinelResource资源的异常处理有两种方式:
blockHandler:sentinel定义的失败调用或限制调用,若本次访问被限流或服务降级,则调用blockHandler指定的接口
fallback:失败调用,若本接口出现未知异常,则调用fallback指定的接口。
当两个都配置时,也就是当出现sentinel定义的异常时,调用blockHandler,出现其它异常时,调用fallback。
2.1 blockhandler 的使用
blockhandler 定义当资源内部发生了BlockException(也就是sentinel定义的失败异常或限制异常),应该走的处理逻辑。
要求:
1.当前方法的返回值和参数要和原方法一致
2.允许在参数列表的最后加入一个参数BlockException,用来接收原方法中发生的异常。

2.2 fallback的使用
要求:
1.当前方法的返回值和参数要和原方法一致
2.允许在参数列表的最后加入一个参数Throwable,用来接收原方法中发生的异常。

2.3 测试



3.怎么将异常处理放在资源类的外面
如果将所有的异常处理都放在资源类里面,会导致类很臃肿,不利于维护,外面可以将异常处理放在类外面


4.@SentinelResource的其它属性
value: Sentinel资源的名称,我们不仅可以通过url进行限流,也可以把此值作为资源名配置,一样可以限流。
entryType: 条目类型(入站或出站),默认为出站(EntryType.OUT)
resourceType: 资源的分类(类型)
blockHandler: 块异常函数的名称,默认为空
blockHandlerClass: 指定块处理方法所在的类
默认情况下, blockHandler与原始方法位于同一类中。 但是,如果某些方法共享相同的签名并打算设置相同的块处理程序,则用户可以设置存在块处理程序的类。 请注意,块处理程序方法必须是静态的。
fallback: 后备函数的名称,默认为空
defaultFallback: 默认后备方法的名称,默认为空
defaultFallback用作默认的通用后备方法。 它不应接受任何参数,并且返回类型应与原始方法兼容
fallbackClass: fallback方法所在的类(仅单个类)
默认情况下, fallback与原始方法位于同一类中。 但是,如果某些方法共享相同的签名并打算设置相同的后备,则用户可以设置存在后备功能的类。 请注意,共享的后备方法必须是静态的。
exceptionsToTrace: 异常类的列表追查,默认 Throwable
exceptionsToIgnore: 要忽略的异常类列表,默认情况下为空。
七 Sentinel整合OpenFeign实现服务降级(服务容错)
如果一个服务(服务消费者)调用了另一个服务(服务生产者),服务生产者有异常,会导致服务消费者出错,我们希望不仅仅只是显示错误,而是能启动熔断器,对服务消费者做降级(容错)处理。
那么应该怎么实现呢?
1.添加jar包
我们当前项目里已添加
<!-- 添加openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.添加配置信息
在服务消费者的配置文件中添加

3.添加降级处理类

4.在feign客户端关联对应的降级处理类

5.在服务提供者中模拟一个异常
比如 int i=1/0;
6.测试

八 Sentinel 规则持久化
Sentinel Dashboard中添加的规则是存储在内存中的,只要项目一重启规则就丢失了
我们可以将规则持久化到nacos中,在nacos中添加规则,然后同步到dashboard中.
方法如下:
1.添加jar包
<!--将持久化到nacos中 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2.在nacos配置中心添加配置文件

[
{
"resource":"/goods",
"limitApp":"default",
"grade":1,
"count":2,
"strategy":0,
"controlBehavior":0,
"clusterMode":false
}
]
注意:
配置格式:选择 json 选项
配置内容:
resource: 资源名称
limitApp: 来源应用
grade: 阈值类型,0表示线程,1表示QPS
count: 单机阈值
strategy: 流控模式,0表示直接,1表示关联,2表示链路
controlBehavior: 流控效果,0表示快速失败,1表示Warm Up,2表示排队等待
clusterMode: 是否集群
3.修改微服务配置信息,添加sentinel规则配置信息到微服务的配置文件中

4.重启服务
配置信息查询
https://github.com/alibaba/Sentinel/wiki
















暂无评论内容