随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
一、下载运行启动
1.1安装
官网下载: https://github.com/alibaba/Sentinel/releases
以java -jar
方式运行 安装下载文件。浏览器输入http://localhost:8080即可进入登录页面。账号密码均为sentinel。
1.2maven引入
<dependencies>
<!--自定义的jar包-->
<dependency>
<groupId>com.charon</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringBoot整合Web组件+actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
1.3配置文件
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#持久化进行nacos
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
只有监控到rest请求才会出现以下界面(这边采用懒加载,并非仅监听项目就可,需要一次请求进入)
二、sentinel控制台介绍
2.1流控规则
①:资源名:唯一名称,默认请求路径。
②:针对来源: Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)·
③:阈值类型/单机阈值
。QPS(每秒钟的请求数量)
︰当调用该api的QPS达到阈值的时候,进行限流。
。线程数
:当调用该api的线程数达到阈值的时候,进行限流。
④:是否集群:不需要集群
⑤:流控模式:
。直接
:api达到限流条件时,直接限流。
。关联
:当关联的资源达到阈值时,就限流自己。
。链路
:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】。
⑥:流控效果:
。快速失败
:直接失败,抛异常。
。Warm Up
:根据codeFactor (冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。
。排队等待
:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效。
2.2降级规则
①RT(平均响应时间 秒级):平均响应时间超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足后触发降级窗口期过后关闭断路器。
RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
②:异常比例:(为满足要求直接报错,满足要求请求提示出友好页面Blocked by Sentinel (flow limiting))QPS >=5且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。
③:异常数:当资源近一分钟的异常数目超过阈值之后进行熔断。注意统计时间窗口是分钟级别的,若timeout小于60s,则结束熔断状态后仍可能在进入熔断。
2.3系统规则(针对于整个系统而言)
①:Load自适应(仅对 Linux/Unix-like机器生效):系统的 load1作为启发指标,进行自适应系统保护。当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段)。系统容量由系统的maxOps * minRt估算得出。设定参考值一般是CPu cores * 2.5。
②:CPU usage (1.5.0+版本)︰当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0) , 比较灵敏。
③:平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
④:并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
⑤:入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护。
2.4热点规则
/**
* 热点规则 报错不会执行blockHandler兜底方法;blockHandler只管控控制台配置
* @param p1 参数1
* @param p2 参数2
* @return
*/
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2) {
//int age = 10/0;
return "------testHotKey";
}
/**
* 自定义返回的友好提示页面
* @param p1 参数1
* @param p2 参数2
* @param exception 异常信息
* @return
*/
public String deal_testHotKey (String p1, String p2, BlockException exception) {
//sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
return "------deal_testHotKey-------";
}
2.5Sentinel介绍
1.Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误
。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)
;
2.Sentinel的断路器是没有半开状态的
:半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。
3.Sentinel主要有三个核心Api:①:SphU定义资源②:Tracer定义统计③:ContextUtil定义了上下文
2.6SentinelResource配置
1.限流模式仅支持QPS
2.SentinelResource配置限流:
@RestController
@Slf4j
public class RateLimitController {
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl() {
return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
}
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
}
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception) {
return new CommonResult(4444,"按客戶自定义,global handlerException----1");
}
public static CommonResult handlerException2(BlockException exception)
{
return new CommonResult(4444,"按客戶自定义,global handlerException----2");
}
}
3.@SentinelResource
处理是控制台的违规情况,有blockHandler方法配置的兜底处理,如果是java运行是异常是不予管理。注解是不支持private方法。
@RequestMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback")
// @SentinelResource(value = "fallback",fallback = "handlerFallback")
//@SentinelResource(value = "fallback",blockHandler = "blockHandler")
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
exceptionsToIgnore = {IllegalArgumentException.class,IndexOutOfBoundsException.class})
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;
}
①:什么都没配置只有value:对于异常和限流都无效,该什么样子就是什么样子。
②:只配置fallback:无法进行限流,但是可以对于异常信息进行捕捉进而执行兜底方法。
③:只配置blockHandler :只可以对于控制台配置进行处理,但是对于异常信息无法处理。遇到异常就将异常信息返回页面。
④:即配置fallback又配置blockHandler:既可以对于异常进行捕捉进而执行兜底方法又可以对于控制台配置管控。如果被限流降级而抛出BlockException时只会进入blockHandler处理逻辑。
⑤:配置exceptionsToIgnore:对于配置异常的出现不走兜底方法,进而直接返回页面错误信息。
2.7Sentinel持久化
2.7.1配置文件添加(如上面配置文件)
#持久化进行nacos
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
2.7.2nacos配置
在添加配置时候选择json格式,配置完如下图所示:
json配置文件内容解析:
配置完毕后当我们重新启动项目,我们所配置的规则就不会消失,再让我们重新配置(一定要先进行一次rest请求)。此时存在一个问题如果配置规则过多我们需要每一个进行填写,还是会耗费大量时间。如果有人看到本文并且有好的解决方案可在评论中附上链接,万分感谢。