Sentinel以流量为切入点,以流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。包括核心的独立类库、监控台、丰富的使用场景。
使用场景:秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
实时监控,开源生态(开箱即用且与其他开源框架/库的整合模块),完善的SPI扩展点(实现扩展,快速定制逻辑,如定制规则逻辑、适配数据流等)
- 资源管理:应用服务器脚本、静态页面、API接口、文件图片等
- 规则配置:允许资源(一般API接口)通过的请求次数,IP黑白名单,应用服务等
- 测试效果:QPS(单台服务器每秒能处理查询次数);TPS(每秒处理的事务数,倾向整个过程)
Sentinel分为两部分:
- 核心库(JAVA客户端)不依赖任何框架/库
- 控制台(Dashboard)基于Spring boot开发,打包直接运行(不需要额外tomcat等应用容器,该模块目前基于Spring boot运行)
# 下面开始整合框架:Nacos注册中心、Feign服务、Sentinel哨兵、Sentinel控制台
一、Sentinel入门介绍
# 搭建2.2.5.RELEASE(与上一文搭建Nacos选了1.4.1版本)sentinel按下图选择的1.8.0版本,下载地址:https://github.com/alibaba/Sentinel/releases
下载到本地后,执行 javaw -jar sentinel-dashboard-1.8.0.jar 默认端口8080( 如果8080端口被占用,可以自定义启动端口java -jar xxx.jar --server.port=8888
)linux 后台启动可以执行 nohup java -jar xxx.jar >log.log &
指定日志文件位置和后台挂起启动
启动成功后访问地址:http://ip:port 默认用户名密码:sentinel
二、搭建Sentinel项目
现在创建一个cloudalbb-sentinel-ribbon1020项目,项目里基本依赖和配置如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
server:
port: 1020
spring:
application:
name: sentinel-ribbon1020
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos集群,使用的是域名
sentinel:
transport:
dashboard: localhost:8080 #配置sentinel dashboard地址
port: 8719 #默认8719端口
service-url:
nacos-service: http://nacos-provider
1、只配置单个blockHandler限流降速处理方法配置
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
return result;
}
public CommonResult<Order> blockHandler(@PathVariable("id") Long id, BlockException exception){
// 不同的异常返回不同的提示语
String reason = "";
if (exception instanceof FlowException) {
reason = "接口限流了";
} else if (exception instanceof DegradeException) {
reason = "服务降级了";
} else if (exception instanceof ParamFlowException) {
reason = "热点参数限流了";
} else if (exception instanceof SystemBlockException) {
reason = "触发系统保护规则";
} else if (exception instanceof AuthorityException) {
reason = "授权规则不通过";
}
Order order = new Order(id, "默认值");
return new CommonResult<Order>(521, "收到请求id:"+id+",sentinel-blockHandler"+reason+":"+exception.getMessage(), order);
}
将nacos-provider和sentinel-ribbon2010两个项目启动,然后配置流量降速,最后访问一下
2、加个blockHandlerClass限流降级处理类配置
为了提高代码的可读性及解耦,将自定义限流降速方法写入一个限流降速级类中,需要时再调用(所有的方法均为static静态方法,参数必须带上BlockException,否则找不到响应方法), blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException ,blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler",blockHandlerClass = BlockHandler.class) //blockHandler只负责sentinel控制台配置违规
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
return result;
}
3、只配置单个fallback熔断降级方法配置
defaultFallback,默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
int test = 10/0;
return result;
}
public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
Order order = new Order(id, "默认值");
return new CommonResult<Order>(520, "收到请求id:"+id+",业务异常:"+throwable.getMessage(), order);
}
4、加个fallbackClass熔断降级处理类配置
@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback",fallbackClass=CustomerFallback.class) //fallback只负责业务异常
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
int test = 10/0;
return result;
}
public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
Order order = new Order(id, "默认值");
return new CommonResult<Order>(520, "收到请求id:"+id+",业务异常:"+throwable.getMessage(), order);
}
5、blockHandler和fallback可以同时配置,不再赘述
exceptionsToIgnore,用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
@GetMapping("/request/pay/{id}")
// blockHandler/blockHandlerClass流速降级,fallback/fallbackClass熔断降速
// @SentinelResource(value="fallback") //无配置
// @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
// @SentinelResource(value = "fallback",fallback = "customerFallback",fallbackClass = CustomerFallback.class) //独立的业务异常处理
// @SentinelResource(value = "fallback",defaultFallback = "defaultFallback") //通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)
// @SentinelResource(value = "fallback",defaultFallback = "customerDefaultFallback",fallbackClass = DefaultFallBack.class) //通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)
// @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class} ) //异常被排除掉,不会进入fallback逻辑中,而是会原样抛出。
public CommonResult<Order> reqToPay(@PathVariable("id") Long id){
CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);
int test = 10/0;
return result;
}
三、集成Spring Cloud OpenFeign
Service层进行注解配置:
@FeignClient(value = "nacos-provider",fallback = PaymentFallbackServiceImpl.class)
@Component
public interface PaymentService {
@GetMapping("/order/{id}")
public CommonResult<Order> getOrderById(@PathVariable("id")Long id);
}
@Component
public class PaymentFallbackServiceImpl implements PaymentService {
@Override
public CommonResult<Order> getOrderById(Long id) {
return new CommonResult<>(444,"服务降级返回,OrderFallbackService",new Order(id,"errorSerial"));
}
}
四、集成RestTemplate
@Bean
@LoadBalanced
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
return new RestTemplate();
}
@SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。
其中 blockHandler 或 fallback 属性对应的方法必须是对应 blockHandlerClass 或 fallbackClass 属性中的静态方法。