一、服务熔断功能

1. Ribbon系列

参考代码:码云 注意提交记录

1.1 整体流程

1.2 配置

  1. 启动nacos和sentinel
  2. 服务提供者cloudalibaba-provider-payment9003/9004 配置和正常的服务提供者一样
  3. 测试所用的controller
@RestController
public class PaymentController
{
   
    @Value("${server.port}")
    private String serverPort;

    public static HashMap<Long, Payment> hashMap = new HashMap<>();
    static{
   
        hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
        hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
        hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
    }

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
   
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort: "+serverPort,payment);
        return result;
    }
}
  1. 消费端 cloudalibaba-consumer-nacos-order84
    主要配置
        <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>
        <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>

server:
  port: 84

spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719

service-url:
  nacos-user-service: http://nacos-payment-provider
  1. 消费端的controller
@RestController
@Slf4j
public class CircleBreakerController {
   

    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;
    //======= OpenFeign
    @Resource
    private PaymentServiceFeign paymentServiceFeign;

    @RequestMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback") //没有任何配置
// @SentinelResource(value = "fallback",fallback ="handlerFallback") //fallback只负责业务异常
    @SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler") //blockHandler只负责Sentinel控制台配置违规
    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("IllegalArgument ,非法参数异常...");
        } else if (result.getData() == null) {
   
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }

        return result;
    }

    public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
   
        Payment payment = new Payment(id, "null");
        return new CommonResult(444, "异常handlerFallback,exception内容: " + e.getMessage(), payment);
    }

    public CommonResult blockHandler(@PathVariable Long id, BlockException e) {
   
        Payment payment = new Payment(id, "null");
        return new CommonResult(444, "blockHandler-sentinel 限流,BlockException: " + e.getMessage(), payment);
    }
}
  1. 消费端的RestTemplate(远程调用)配置负载均衡
@Configuration
public class ApplicationContextConfig {
   

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
   
        return new RestTemplate();
    }
}

1.3 测试

1.3.1没有任何配置

http://localhost:84/consumer/fallback/4
前提没有限流和降级处理 出现异常直接返回Errorpage

1.3.2只配置fallback

处理业务中的异常

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback",fallback ="handlerFallback")  //fallback只负责业务异常
    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("IllegalArgument ,非法参数异常...");
        } else if (result.getData() == null) {
   
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }
	}
	 public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
   
        Payment payment = new Payment(id, "null");
        return new CommonResult(444, "异常handlerFallback,exception内容: " + e.getMessage(), payment);
    }

访问http://localhost:84/consumer/fallback/4 一定会出现异常
并没有返回异常页面 而是调用handlerFallback方法

SentinelResource的·fallback·:针对于方法级别的处理 <mark>注意</mark>:方法的返回值请求参数对应 并且添加一个异常方法Throwable e
springmvc:全局异常异常处理:针对于异常类型进行处理
配置fallback出现异常走指定的fallback方法 控制台<mark>不会进行打印异常</mark>

1.3.3只配置blockHandler

@RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback", blockHandler = "blockHandler")//blockHandler只负责Sentinel控制台配置违规
    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("IllegalArgument ,非法参数异常...");
        } else if (result.getData() == null) {
   
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }
        return result;
    }
    public CommonResult blockHandler(@PathVariable Long id, BlockException e) {
   
    	Payment payment = new Payment(id, "null");
    	return new CommonResult(444, "blockHandler-sentinel 限流,BlockException: " + e.getMessage(), payment);
    }

访问localhost:84/consumer/fallback/4 一定会抛出异常

第一次访问

第二次 访问 和第一次一样

第三次访问
已经进行熔断了

1.3.4 fallback和blockHandler都配置

前两次使用fallback
两次异常触发了降级 使用blockHandler方法

1.3.5 结论

fallback:只负责业务异常
blockHandle:只负责Sentinel控制台配置违规 使用该属性只是替换默认的违规提示
参考博文:你知道Sentinel限流、降级的统一处理吗?

2. Feign系列

pom

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

yml


#对Feign的支持
feign:
  sentinel:
    enabled: true
//远程调用service
//fallback 熔断调用的类
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
   
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
 
//熔断实现类
@Component
public class PaymentFallbackService implements PaymentService
{
   
    @Override
    public CommonResult<Payment> paymentSQL(Long id)
    {
   
        return new CommonResult<>(44444,"服务降级返回,---PaymentFallbackService",new Payment(id,"errorSerial"));
    }
}

二、熔断框架对比

同类组件功能对比

Sentinel Hystrix resilience4j
隔离策略 信号量隔离(并发控制) 线程池隔离/信号量隔离 信号量隔离
熔断降级策略 基于慢调用比例、异常比例、异常数 基于异常比例 基于异常比例、响应时间
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于 RxJava) Ring Bit Buffer
动态规则配置 支持近十种动态数据源 支持多种数据源 有限支持
扩展性 多个扩展点 插件的形式 接口的形式
基于注解的支持 支持 支持 支持
单机限流 基于 QPS,支持基于调用关系的限流 有限的支持 Rate Limiter
集群流控 支持 不支持 不支持
流量整形 支持预热模式与匀速排队控制效果 不支持 简单的 Rate Limiter 模式
系统自适应保护 支持 不支持 不支持
热点识别/防护 支持 不支持 不支持
多语言支持 Java/Go/C++ Java Java
Service Mesh 支持 支持 Envoy/Istio 不支持 不支持
控制台 提供开箱即用的控制台,可配置规则、实时监控、机器发现等 简单的监控查看 不提供控制台,可对接其它监控系统

三、持久化

maven配置

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

yml配置

spring:
  application:
    name: cloudalibaba-sentinal-service
  cloud:
    nacos:
      discovery:
        #Nacos服务注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentin dashboard地址
        dashboard: localhost:8080
        port: 8719 # 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
      datasource: #持久化配置
        ds1:  
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

nacos中

[
    {
   
         "resource": "/retaLimit/byUrl",
         "limitApp": "default",
         "grade":   1,
         "count":   1,
         "strategy": 0,
         "controlBehavior": 0,
         "clusterMode": false    
    }
]


启动8401后刷新sentinel发现业务规则有了

结论:
会把nacos中配置的同步到sentinel <mark>注意</mark>在sentinel界面中配置的不会添加到nacos中