Sentinel服务熔断与限流(二)@SentinelResouece配置、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、上面兜底方案面临的问题

  1. 系统默认的,没有体现我们的业务要求

  2. 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观

  3. 每个业务方法都添加一个兜底的,那代码膨胀加剧

  4. 全局统一的处理方法没有体现

4、客户自定义限流处理逻辑

  1. 创建CustomerBlockHandler类用于自定义限流处理逻辑

  2. 自定义限流处理类

  3. RateLimitController

  4. 启动微服务后先调用一次

  5. Sentinel控制台配置

  6. 测试后我们自定义的出来了

@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注解包含以下属性:

  1. value:资源名称,必填项。
  2. entryType:entry类型,可选项(默认为EntryType.OUT)
  3. blockHandler/blockHandlerClassblockHandler对应处理BlockException的函数名称,可选项。blockHandler函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException。blockHandler函数默认需要和原方法再同一个类中,若希望使用其他类的函数,则可以指定blockHandlerClass为对应的类的class对象,注意,对应的函数必须为static函数,否则无法解析。
  4. fallback:fallback函数名称,可选项,用于再抛出异常的时候提供的fallback处理逻辑,fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要和原函数一致,或者可以额外多一个Throwable类型的参数用于接收对应的异常;
    • fallback函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定fallbackClass为对应的类的class对象,注意对应的函数必须为static函数,否则无法解析
  5. defaultFallback(since 1.6.0):默认的fallback函数名称,可选项,通常用于通用的fallback逻辑(即可以用于很多服务或方法),默认fallback函数可以针对所有类型的异常(除了exceptionsToIgore里面排除掉的异常类型)进行处理若同时配置了fallback和defaultFallback,则只有fallback会生效,defaultFallback函数要求如下:
    • 返回值类型必须与原函数返回值类型一致
    • 方法参数列表需要为空,或者可以额外多一个Throwable类型的参数用于接收对应的异常。
    • defaultFallback函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定fallbackClass为对应的类的class对象,注意对应的函数必须为static函数,否则无法解析
  6. exceptionsToIgnore(since 1.6.0):用于指定那些异常被排除掉,不会级如异常统计中,也不会进入fallback逻辑中,而是原样抛出。

注意:11.6.0之前的版本fallback函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理

特别的,若blockHandler和fallback都进行了配置,则被限流降级而抛出BlockException时只会进入blockHandler处理逻辑,若未配置blockHandlerfallbackdefaultFallback,则被限流降级时会将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、熔断框架比较

SentinelHystrix
隔离策略信号量隔离(并发线程数限流)线程池隔离/信号量隔离
熔断降级策略基于响应时间、异常比率、异常数基于异常比率
实时统计实现滑动窗口(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

发现流控规则还在

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值