Sentinel 是什么
Sentinel是阿里进一步将hystrix 进行封装,减少降级,熔断,限流等相关代码编写,实现页面平台上配置就可以控制服务的降级,熔断,限流等操作的触发值。是分布式系统的流量防卫兵。
Sentinel 下载和安装
- 登入https://github.com/alibaba/Sentinel/releases 找到对应分支下载jar包
- 使用 java -jar sentinel.jar 命令启动服务
- 登入 localhost:8080 ,用户名和密码都是sentinel 登入查看。
搭建一个服务查看其请求可以被Sentinel监控到
- 添加依赖
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 配置yml文件
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
port: 8719 # 默认监听端口 没有找到会自增1 直到找到为止
management:
endpoints:
web:
exposure:
include: '*'
- 启动类
@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401
{
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}
- 测试业务类
@RestController
@Slf4j
public class FlowLimitController
{
@GetMapping("/testA")
public String testA()
{
return "------testA";
}
@GetMapping("/testB")
public String testB()
{
log.info(Thread.currentThread().getName()+"\t"+"...testB");
return "------testB";
}
}
启动nacos,测试业务服务,sentinel 登入sentinel页面查看信息
注意sentinel是懒加载模式,所以要发送一个请求,页面上才会显示。
Sentinel 流控规则
-
具体: 默认高级设置
-
关联代表 当B请求超过流量配置时,关联的A请求就也不能请求
-
Warm Up 预热配置 默认是3为最低值,单机阀值为最大值,即在一段时间内由3慢慢的加到单机阀值。图中是5秒。
-
排队模式
Sentinel 降级规则
-
RT(平均响应时间,秒级)
平均响应时间 超出阈值 且 在时间窗口内通过的请求>=5,两个条件同时满足后触发降级
窗口期过后关闭断路器
RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效) -
异常比列(秒级)
QPS >= 5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级 -
异常数(分钟级)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
Sentinel 热点规则
根据请求参数来设定降级触发点。
例如添加如下请求
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey") // 类似hystrixCommand 注解 用来自定义降级处理
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2)
{
//int age = 10/0;
return "------testHotKey";
}
public String deal_testHotKey (String p1, String p2, BlockException exception)
{
return "------deal_testHotKey,o(╥﹏╥)o"; //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
}
高级设置:参数例外项 可以设置p1的参数为特殊值时,重新设置降级触发点,例如下图为p1等于5时,一秒可以发送200次最大。
Sentinel 系统规则
对于整个系统进行降级控制
- Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
- CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
- RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
Sentinel @SentinelResource 注解用法
sentinel页面上设置降级触发点 可以通过注解的value设置也可以通过mapping的url路径配置。
除了上一种直接设置自定义降级方法,还可以调用公共类的公共方法
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class, // 公共降级类
blockHandler = "handlerException2") // 公共降级方法
public CommonResult customerBlockHandler()
{
return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
- fallback/blockHandler/exceptionsToIgnore 属性的区别
fallback当抛出业务异常时执行该对应的降级方法。
blockHandler当sentinel控制台配置的规则违反时执行该对应的降级方法。
exceptionsTolgnore 指定某个异常发生时不执行fallback的降级方法,直接抛出ERROR PAGE画面。
实例如下:
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", // sentinel控制台的权限更大
exceptionsToIgnore = {IllegalArgumentException.class}) // 抛出IllegalArgumentException异常不管,不进行fallback降级处理
public CommonResult<Payment> fallback(@PathVariable Long id)
{
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
//本例是fallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
}
//本例是blockHandler
public CommonResult blockHandler(@PathVariable Long id,BlockException blockException) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment);
}
- 不用restTemplate实现服务之间的调用,而使用OpeanFigin来实现服务直接调用。OpeanFigin的降级方法处理和原来一样
···java
@FeignClient(value = “nacos-payment-provider”,fallback = PaymentFallbackService.class)
public interface PaymentService
{
@GetMapping(value = “/paymentSQL/{id}”)
public CommonResult paymentSQL(@PathVariable(“id”) Long id);
}
···
Sentinel 持久化操作
由于Sentinel 没有持久化特性,即重启Sentinel,其配置的流控规则,降级规则,热点规则等都会没有。所以要自己配置一个持久化的操作。将其配置到nacos的配置中心去
- 添加依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- 配置yml文件 添加对应nacos配置中心信息 添加的是datasource 那一段
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
port: 8719 # 默认监听端口 没有找到会自增1 直到找到为止
datasource:
ds1:
nacos:
server-addr: localhost:8848 # nacos的配置中心地址
dataId: cloudalibaba-sentinel-service # 配置中心的DataID
groupId: DEFAULT_GROUP # 配置中心的分组
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
- 到nacos配置中心画面上添加对应流控规则,将其规则和服务进行绑定,当服务启动后,调用多次会自动将规则添加到Sentinel中。
启动项目,查看Sentinel的规则是否跟着改变。