目录
- 七、@SentinelResouece配置
- 1、按资源名称限流+后续处理
- 2、按照URL地址限流+后续处理
- 3、上面兜底方案面临的问题
- 4、客户自定义限流处理逻辑
- 5、更多注解属性说明
- 八、Sentinel服务熔断功能
- 1、sentinel整合ribbon + openFeign + fallback
- 1、Ribbon系列
- 1、提供者
- 1、添加pom文件
- 2、修改yml配置
- 3、修改启动类
- 4、修改业务类
- 5、测试地址
- 2、消费者84
- 1、添加pom配置、添加yml配置
- 2、修改启动类
- 3、添加业务类
- 4、测试结果
- 5、异常忽略
- 3、Feign系列
- 1、添加pom依赖
- 2、修改yml配置
- 3、修改启动类
- 4、修改业务类
- 5、测试
- 4、熔断框架比较
- 九、规则持久化
- 1、介绍
- 2、使用步骤
- 1、添加pom文件依赖
- 2、添加yml配置
- 3、添加Nacos业务配置规则
- 4、启动8401后刷新sentinel发限业务规则有了
- 6、快速放测试接口
- 7、停止8401再看sentinel
- 8、重启8401再看sentinel
七、@SentinelResouece配置
1、按资源名称限流+后续处理
1、启动Nacos成功
2、启动Sentinel成功
@GetMapping("/byResource")
@SentinelResource(value="byResource",blockHandler="handlerException")
public CommonResult byResource(){
return new CommonResult(200,"按资源名称限流测试ok",new Payment(2020L,"serial001"));
}
public CommonResuslt handleExcapeion(BlockException exception){
return new CommonResult(444,exception.getClass().getCanonicaName()+"\t 服务不可用");
}
超过上述,疯狂点击,返回了自己定义的限流处理信息,限流发生
{"code":"444","message":"com.alibaba.csp.sentinel.slots.block.flow.FlowException\t服务不可用","data":null}
2、按照URL地址限流+后续处理
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value="byUrl")
public CommonResult byUrl(){
return new CommonResult(200,"按url限流测试ok",new Payment(2020L,"serial002"));
}
会返回Sentinel自带的限流处理结果
3、上面兜底方案面临的问题
- 系统默认的,没有体现我们的业务要求
- 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观
- 每个业务方法都添加一个兜底的,那代码膨胀加剧
- 全局统一的处理方法没有体现
4、客户自定义限流处理逻辑
- 创建CustomerBlockHandler类用于自定义限流处理逻辑
- 自定义限流处理类
- RateLimitController
- 启动微服务后先调用一次
- Sentinel控制台配置
- 测试后我们自定义的出来了
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value="customerBlockHandler",
//指定我们共有类里面的具体的哪个方法
blockHandlerClass=CustomerBlockHandler.class,blockHandler="handlerException2")
public CommonResult customerBlockHandler(){
return new CommonResult(200,"按客户自定义限流处理逻辑")
}
/**
* 自定义的共有类
*/
public class CustomerBlockHandler{
public static CommonResult handleException(BlockException exception){
return new CommonResult(2020,"客户自定义的限流信息。。。。customerBlockHandler");
}
public static CommonResult handleException2(BlockException exception){
return new CommonResult(4444,"按客户自定义,global handlerException——2");
}
}
5、更多注解属性说明
注意:注解方式不支持private方法。
@SentinelResource
用于定于资源,并提供可选的异常处理和fallback配置项,@SentinelResource
注解包含以下属性:
-
value
:资源名称,必填项。 -
entryType
:entry类型,可选项(默认为EntryType.OUT) -
blockHandler
/blockHandlerClass
:blockHandler
对应处理BlockException
的函数名称,可选项。blockHandler函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException
。blockHandler函数默认需要和原方法再同一个类中,若希望使用其他类的函数,则可以指定blockHandlerClass
为对应的类的class对象
,注意,对应的函数必须为static函数,否则无法解析。 fallback
:fallback函数名称,可选项,用于再抛出异常的时候提供的fallback处理逻辑,fallback函数可以针对所有类型的异常(除了exceptionsToIgnore
里面排除掉的异常类型)进行处理。
- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要和原函数一致,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常; - fallback函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的class
对象,注意对应的函数必须为static
函数,否则无法解析
defaultFallback
(since 1.6.0):默认的fallback函数名称,可选项,通常用于通用的fallback逻辑(即可以用于很多服务或方法),默认fallback函数可以针对所有类型的异常(除了exceptionsToIgore
里面排除掉的异常类型)进行处理若同时配置了fallback和defaultFallback,则只有fallback会生效,defaultFallback函数要求如下:
- 返回值类型必须与原函数返回值类型一致
- 方法参数列表需要为空,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常。 - defaultFallback函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的class
对象,注意对应的函数必须为static
函数,否则无法解析
-
exceptionsToIgnore
(since 1.6.0):用于指定那些异常被排除掉,不会级如异常统计中,也不会进入fallback逻辑中,而是原样抛出。
注意:11.6.0之前的版本fallback函数只针对降级异常(
DegradeException
)进行处理,不能针对业务异常进行处理
特别的,若blockHandler和fallback都进行了配置,则被限流降级而抛出BlockException
时只会进入blockHandler处理逻辑,若未配置blockHandler
、fallback
和defaultFallback
,则被限流降级时会将BlockException直接抛出(若方法本身未定义throws BlockException则会被JVM包装一层UndeclaredThrowableException
)。
八、Sentinel服务熔断功能
1、sentinel整合ribbon + openFeign + fallback
1、Ribbon系列
先启动nacos和sentinel
创建提供者9003和9004两个一样的做法
1、提供者
1、添加pom文件
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2、修改yml配置
server:
port: 9003 #另一个9004,下面其他配置雷同
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'
3、修改启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003{
public static void main(Stringp[] args){
SpringApplpication run(PaymentMain9003.class,args);
}
}
4、修改业务类
@RestController
public class PaymentController{
@Value("${server.port}")
private String serverPort;
public static HashMap<Long,Payment> hashMap = new HashMap<>();
@GetMapping(value="/paymentSQL/{id}")
public CommonResult<PaymentSQL>(@PathVariable("id") Long id){
hashMap.put(1L,new Payment(1L,"123"));
hashMap.put(2L,new Payment(2L,"222"));
hashMap.put(3L,new Payment(3L,"333"));
Payment payment =hashMap.get(id);
CommonResult<Payment> result = new CommonResult(200,"from mysql,
serverPort:"+serverPort,payment");
return result;
}
5、测试地址
http://localhost:9003/paymentSQL/1
2、消费者84
1、添加pom配置、添加yml配置
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#配置sentinel dashboard地址
dashboard: localhost:8080
#默认端口8719,加入被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
service-url:
nacos-user-service: http//nacos-payment-provider
2、修改启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderNacosMain84{
public static void main(Stringp[] args){
SpringApplpication.run(OrderNacosMain84.class,args);
}
}
3、添加业务类
ApplicationContextConfig
@Configuration
public class ApplicationContextConfig{
@Bean
@LoadBalanced //开启负载均衡
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
CircleBreakerController
@RestController
public class CircleBreakerController{
public static final String SERVICE_URL="http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value="fallback") //没有配置
// fallback只负责业务异常
//@SentinelResource(value="fallback",fallback="handlerFallback")
// blockHandler只负责sentinel控制台配置违规
//@SentinelResource(value="fallback",blockHandler="blockHandler")
//@SentinelResource(value="fallback",fallback="handlerFallback",
// blockHandler="blockHandler")
public CommonResult<Payment> fallback(@PathVariable Long id){
CommonResult<Payment> result = restTemplate.getForObjecct(
SERVICE_URL+"/paymentSQL/"+id,CommonResult.class,id);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException,非法参数异常。。");
}else if(result.getData()==null){
throw new NullpointerException("NullPointerException,ID没有对应记录,空指针异常");
}
}
//本例是fallback
/**public CommonResult handlerFallback(@PathVirable Log id,Throwable e){
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容为"
+e.getMessage(),payment);
}*/
//本例是blockHandler
/**public CommonResult blockHandler(@PathVirable Log id,BlockException e){
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水,blockException "
+e.getMessage(),payment);
}*/
}
4、测试结果
若blockHandler和fallback都进行了配置,则被限流降级而抛出BlockException时只会进入blockHandler处理逻辑
5、异常忽略
@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value="fallback",fallback="handlerFallback",blockHandler="blockHandler",
exceptionsToIgnore = {IllegalArgumentException.class})//配置异常忽略
public CommonResult<Payment> fallback(@PathVariable Long id){
CommonResult<Payment> result = restTemplate.getForObjecct(
SERVICE_URL+"/paymentSQL/"+id,CommonResult.class,id);
if(id == 4){
//假如抛出此异常,不再用fallback方法兜底,没有降级效果了
throw new IllegalArgumentException("IllegalArgumentException,非法参数异常。。");
}else if(result.getData()==null){
throw new NullpointerException("NullPointerException,ID没有对应记录,空指针异常");
}
}
//本例是fallback
public CommonResult handlerFallback(@PathVirable Log id,Throwable e){
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容为"
+e.getMessage(),payment);
}
//本例是blockHandler
public CommonResult blockHandler(@PathVirable Log id,BlockException e){
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水,blockException "
+e.getMessage(),payment);
}
3、Feign系列
修改84模块。然后启动9003不启动9004
1、添加pom依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--spring cloud openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、修改yml配置
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#配置sentinel dashboard地址
dashboard: localhost:8080
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
servier-url:
nacos-user-service: http://nacos-payment-provider
#激活sentinel对Feign的支持
feign:
sentinel:
enabled: true
3、修改启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderNacosMain84{
public static void main(Stringp[] args){
SpringApplpication.run(OrderNacosMain84.class,args);
}
}
4、修改业务类
//业务类
@FeignClient(value="nacos-payment-provider",fallback=PaymentFallbackService.class)
public interface PaymentService{
@GetMapping(value="/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
//业务降级返回fallback
@Component
public class PaymentFallbackService implements PaymentService{
@Override
public CommonResult<Payment> paymentSQL(Long id){
return new CommonResult<>(44444,"服务降级返回,---PaymentFallbackService",
new Payment(id,"errors"));
}
}
controller类
@Resource
private PaymentService paymentService;
@GetMapping(value="/consumer/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id")Long id){
return paymentService.paymentSQL(id);
}
5、测试
http://localhost:84/consumer/openfeign/1
测试84调用9003,此时故意关闭9003微服务提供者
,看84消费测自动降级,不会被耗死
4、熔断框架比较
Sentinel | Hystrix | |
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于RxJava) |
动态规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持 |
九、规则持久化
1、介绍
一旦我们重启应用,sentinel规则将会消失,生产环境需要将配置规则进行持久化
将先流规则配置持久化进Nacos保存(Nacos已进行mysql持久化了),只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效
2、使用步骤
1、添加pom文件依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2、添加yml配置
添加Nacos数据源配置
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
3、添加Nacos业务配置规则
- resource:资源名称
- limitApp:来源应用
- grade:阈值类型,0表示线程数,1表示QPS
- count:单机阈值
- strategy:流控模式,0表示直接,1表示关联,2表示链路
- controlBehavior:流控效果,0表示快速失败,1表示Warm up,2表示排队等待
- clusterMode:是否集群
4、启动8401后刷新sentinel发限业务规则有了
6、快速放测试接口
7、停止8401再看sentinel
8、重启8401再看sentinel
发现流控规则还在