Sentinel是什么
Sentinel英文翻译"哨兵\门卫",是Spring Cloud Alibaba提供的微服务组件,随着微服务的流行,服务和服务之间的稳定性变得越来越重要。
Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel的作用及其应用场景
为了保证服务器运行的稳定性,在请求数到达设计最高值时,将过剩的请求限流,保证在设计的请求数内的请求能够稳定完成处理。
-
丰富的应用场景
双11,秒杀,12306抢火车票 -
完备的实时状态监控
可以支持显示当前项目各个服务的运行和压力状态,分析出每台服务器处理的秒级别的数据
-
广泛的开源生态
很多技术可以和Sentinel进行整合,SpringCloud,Dubbo,而且依赖少配置简单
-
完善的SPI扩展
Sentinel支持程序设置各种自定义的规则
Sentinel启动
windows系统直接双击start-sentinel.bat文件
mac系统使用下面命令执行jar包
java -jar sentinel-dashboard-1.8.2.jar
启动之后
打开浏览器http://localhost:8080/
会看到下面的界面
用户名和密码都是
sentinel
刚开始什么都没有,是空界面
后面我们有控制器的配置就会出现信息了
基本配置
我们的限流针对的是控制器方法
我们找一个简单的模块来测试和观察限流效果
在csmall-stock-webapi模块中
添加sentinel的依赖
<!-- Sentinel的依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
application-dev.yml文件添加配置
spring:
cloud:
sentinel:
transport:
# 配置sentinel提供的仪表台的位置
dashboard: localhost:8080
# 执行限流的端口号,每个项目需要设置不同的端口号
# 当前是stock模块,如果后续cart模块也要在本地启动并限流,端口号就可以设置为8722
port: 8721
nacos:
discovery:
# 配置Nacos的位置,用于提交当前项目信息
server-addr: localhost:8848
自定义限流方法
对于被限流的请求,我们可以自定义限流的处理方法
默认情况下可能不能正确给用户提示,一般情况下,对被限流的请求也要有"服务器忙请重试"或类似的提示
StockController类中@SentinelResource注解中,可以自定义处理限流情况的方法
@PostMapping("/reduce/count")
@ApiOperation("减少库存数的功能")
// @SentinelResource注解需要编写在控制层方法上,在该方法运行一次后,会被sentinel仪表台检测
// 如果这个方法不运行,sentinel仪表台是无法显示这个方法的
// 括号里"减少库存数"这个描述,会显示在仪表台上,作为当前方法的名称
// blockHandler是注解中的属性,它可以指定当请求被限流时,自定义运行的方法名称,blockError是自定义的名称
@SentinelResource(value = "减少库存数",blockHandler = "blockError")
public JsonResult reduceStock(StockReduceCountDTO stockReduceCountDTO){
// 调用业务逻辑层方法,如果发生异常,将由全局异常处理类处理
stockService.reduceStockCount(stockReduceCountDTO);
return JsonResult.ok("库存减少完成!");
}
// Sentinel自定义限流方法定义规则
// 1.访问修饰符必须是public
// 2.返回值类型必须和控制器方法一直
// 3.方法名必须和@SentinelResource注解定义的方法名对应
// 4.方法的参数和控制器方法参数一致,然后再额外添加一个参数BlockException表示限流异常
public JsonResult blockError(StockReduceCountDTO stockReduceCountDTO,
BlockException e){
// 这个方法运行表示当前请求被限流了,给出相应,提示当前用户被限流
return JsonResult.failed(
ResponseCode.INTERNAL_SERVER_ERROR,"服务器忙,请稍后再试");
}
重启stock-webapi模块
再次尝试被限流,观察被限流的提示
QPS与并发线程数
-
QPS:是每秒请求数
单纯的限制在一秒内有多少个请求访问控制器方法
-
并发线程数:是当前正在使用服务器资源请求线程的数量
限制的是使用当前服务器的线程数
并发线程数测试可能需要阻塞当前控制器方法一段时间,方便测试
@SentinelResource(value = "减少库存数",blockHandler = "blockError")
public JsonResult reduceStock(StockReduceCountDTO stockReduceCountDTO){
// 调用业务逻辑层方法,如果发生异常,将由全局异常处理类处理
stockService.reduceStockCount(stockReduceCountDTO);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return JsonResult.ok("库存减少完成!");
}
自定义降级方法
所谓降级就是正常运行控制器方法的过程中
控制器方法发生了异常,Sentinel支持我们运行别的方法来处理异常,或运行别的业务流程处理
我们也学习过处理控制器异常的统一异常处理类,和我们的降级处理有类似的地方
但是Sentinel降级方法优先级高,而且针对单一控制器方法编写
StockController类中@SentinelResource注解中,可以定义处理降级情况的方法
// fallback是注解中的属性,它可以指定当控制器方法运行发生异常时,运行指定的方法,优先级比统一异常处理高
@SentinelResource(value = "减少库存数",
blockHandler = "blockError",
fallback = "fallbackError")
public JsonResult reduceStock(StockReduceCountDTO stockReduceCountDTO){
// 调用业务逻辑层方法,如果发生异常,将由全局异常处理类处理
stockService.reduceStockCount(stockReduceCountDTO);
if(Math.random()<0.5){
throw new CoolSharkServiceException(
ResponseCode.INTERNAL_SERVER_ERROR,"随机异常");
}
return JsonResult.ok("库存减少完成!");
}
// 限流方法略...
// 自定义降级方法定义规则和限流方法基本一致
// 参数中额外的返回值类型变化为Throwable
// 当控制器方法运行有异常时,会运行这个方法,异常对象会被Throwable接收
// 实际开发中可以运行之前较老版本的代码,所以叫"降级"
public JsonResult fallbackError(StockReduceCountDTO stockReduceCountDTO,
Throwable throwable){
// 输出异常信息到控制台
throwable.printStackTrace();
// 返回降级方法的运行消息
return JsonResult.failed(
ResponseCode.INTERNAL_SERVER_ERROR,"方法异常,服务降级");
}
重启csmall-stock-webapi模块测试
当发生随机异常时,就运行降级方法
当没有发生随机异常时,就正常运行!
总的来说,Sentinel的主要作用就是限流和降级,在控制层使用@SentinelResource注解来实现。