Sentinel
介绍
Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。包括核心的独立类库,监控台,丰富的使用场景验证。(这似乎是阿里开源组件的一贯作风,极其有特点,且特点很规律)
注:官网给出的中间件的基本使用思路与核心功能点
框架环境整合
启动Sentinel
-
下载
还是一样的在阿里的GitHub官网下载 sentinel
注意:这里启动的话,需要在本地环境里配置jdk的;不然不好启动的 -
启动服务
这里需要在目录环境下,启动cmd,然后启动命令
java -jar sentinel-dashboard-1.7.2.jar
注意:不同的版本 后面的版本号需要修改
启动后,访问http://localhost:8080 登录账号密码均为sentinel
搭建微服务
这里创建一个单独的微服务来学习sentinel;这里的注册中心是用nacos,需要提前启动,这里就不描述了,如果有需要改其他的注册中心也可以,不过需要注意依赖配置不要弄错
- pom
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
- 配置文件
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
- 启动类
@EnableDiscoveryClient
@SpringBootApplication
public class SentinelApplication
{
public static void main(String[] args) {
SpringApplication.run(SentinelApplication.class, args);
}
}
- controller 测试代码
@RestController
public class TestController
{
@GetMapping("/testA")
public String testA() {
return "------testA";
}
@GetMapping("/testB")
public String testB() {
return "------testB";
}
}
启动测试
访问任意的路径,sentinel是默认懒加载的,所以在访问url的时候,才会添加
流控规则
在搭建完环境后,简单了解了sentinel的使用,流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
单条限流规则主要由以下几个因素组成,我们可以组合这些元素实现不同的限流效果:
- resource : 资源名,即限流规则的作用对象
- count : 限流阈值
- grade : 限流阈值类型(QPS或是并发线程数)
- limitApp : 流控针对的调用来源,若为default 则不区分来源
- strategy : 调用关系限流策略
- controlBehavior :流量控制效果(直接拒绝,Warm Up,均速排队)
配置使用
资源名:唯一名称,默认是请求路径,可自定义(后续讲解)。
针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制。
阈值类型/单机阈值:QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流 / 线程数:当调用该接口的线程数达到阈值的时候,进行限流 。
是否集群:是否集群配置
sentinel共有三种流控模式,分别是:
直接(默认):接口达到限流条件时,开启限流。
关联:当关联的资源达到限流条件时,开启限流 (适合做应用让步)。
链路:当从某个接口过来的资源达到限流条件时,开启限流。
直接流控模式
直接流控模式是最简单的模式,当指定的接口达到限流条件时开启限流。前面的两个案例都是默认直接流控。
关联流控模式
关联流控模式指的是,当指定接口关联的接口达到限流条件时,开启对指定接口开启限流。
效果
在配置好以后连续多次快速访问后,就会出现报错的访问,这个时候就会对其有限制作用
降级规则
配置介绍
我们针对资源/test-a进行降级设置,Sentinel具有3种降级策略,我们来一一说明
RT:平均响应时间 (DEGRADE_GRADE_RT);当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下来的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。
注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
我们来个流程图更清晰点
异常比例
异常比例:当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
我们也来上个图:
异常数
异常数:当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。所以时间窗口一定要大于等于60秒。
上面阐述了Sentinel的降级设置,还是比较灵活的;还有一点就是Sentinel的断路器是没有半开状态的,也许之后的版本会有。
实现配置
这样配置保存后,再1s内多次访问后也会快速熔断,在接下来的休眠时间窗中,会继续保持这个错误,当然错误提示跟限流的都是一样,走的是系统配置的默认错误
热点规格
这是对复合规则的入参的一种限制
代码
@RequestMapping("/testC")
@SentinelResource("/HotspotRules") //注意这里必须使用 @SentinelResource 这个注解标识,否则热点规则不生效
public String testMessageFunction4(@RequestParam(required = false) String a,
@RequestParam(required = false)String b) {
return a + " -- "+ b ;
}
配置页
-
限流模式:只有QPS模式(这才叫热点)。
-
参数索引:代表@SentinelResource注解的方法参数,0代表第一个参数,1代表第二个参数。
-
单机阀值以及统计窗口时长:表示在此窗口时间超过阀值就限流。
代码
注:这里配置的意思是当第一个参数有参的时候,在1秒内多次访问的时候,就会限流
没有第一个参数就会正常
高级配置
总结
热点参数其实说白了就是特殊的流控,流控设置是针对整个请求的;但是热点参数他可以设置到具体哪个参数,甚至参数针对的值,这样更灵活的进行流控管理。
一般应用在某些特殊资源的特殊处理,如:某些商品流量大,其他商品流量很正常,就可以利用热点参数限流的方案
SentinelResource
代码改造
在这里我们基本上都是使用sentinel的默认配置,走的都是默认的降级服务和默认的熔断;但是这种在代码中使用还是很不友好的,所有我们一般使用,配置使用好的
@GetMapping("/testA")
@SentinelResource(value = "testA",blockHandler = "exceptionHandler", fallback = "fallback")
public String testA() {
return "------testA";
}
// 降级处理
public String fallback() {
return "服务降级,id=";
}
// 异常处理
public String exceptionHandler( BlockException be) {
be.printStackTrace();
return "服务抛异常,id=";
}
@SentinelResource
value:表示配置控制台的资源名称
blockHandler:表示是熔断时候提示的错误
fallback:表示是降级服务
注:这里可以这样理解blockHandler和fallback,fallback处理业务逻辑的异常,服务降级,blockHandler处理sentinel组件控制的阻断异常。
总结:这样的配置代码后,再在控制台配置对应的限制规则,启动后,就会使用对应的降级规格和熔断服务;
自定义异常
- 首先定义一个类放异常方法
public class CustomerBlockHandler {
public static String handleException(BlockException exception) {
return "自定义限流处理信息....CustomerBlockHandler";
}
}
- 配置controller
@GetMapping("/rateLimit/customerBlockHandler")
//blockHandlerClass 指定使用的异常类, blockHandler指定异常类中的异常方法
@SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException")
public String customerBlockHandler()
{
return "按客戶自定义";
}
对fegin的支持
Sentinel 适配了 Feign 组件。如果想使用,除了引入 sentinel-starter 的依赖外还需要 2 个步骤:
配置文件打开 sentinel 对 feign 的支持: feign.sentinel.enabled=true
加入 openfeign starter 依赖使 sentinel starter 中的自动化配置类生效:
- 引入依赖
父工程pom
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
当前微服务
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 开启sentinel支持
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
feign:
sentinel:
enabled: true #激活sentinel的支持
- 配置FeginClient
/**
* 声明需要调用的微服务名称
* @FeignClient
* * name : 服务提供者的名称
* * fallback : 配置熔断发生降级方法
* 实现类
*/
@FeignClient(name="service-product",fallback = ProductFeignClientCallBack.class)
public interface ProductFeignClient {
/**
* 配置需要调用的微服务接口
*/
@RequestMapping(value="/product/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable("id") Long id);
}
- 配置熔断方法
@Component
public class ProductFeignClientCallBack implements ProductFeignClient {
/**
* 熔断降级的方法
*/
public Product findById(Long id) {
Product product = new Product();
product.setProductName("feign调用触发熔断降级方法");
return product;
}
}
总结
Hystrix的核心点在于以隔离和熔断为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制;
Sentinel核心点在于流量控制多样化,熔断降级服务,系统负载保护,实时监控和控制台;
补刀一句:对于流量控制类的组件,大部分场景是使用限流,服务降级这两块核心功能