使用Sentinel实现服务熔断和降级

使用 Sentinel 实现服务熔断和降级

  • 使用 Sentinel 实现限流 , 参见 springcloud-demo , 限流是给服务生产者的保护措施

    • 添加 pom 依赖

      <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
        <version>2.2.0.RELEASEversion>
      dependency>
      <dependency>
        <groupId>com.alibaba.cspgroupId>
        <artifactId>sentinel-datasource-nacosartifactId>
        <version>1.7.1version>
      dependency>
      
      <dependency>
        <groupId>com.alibaba.cspgroupId>
        <artifactId>sentinel-apache-dubbo-adapterartifactId>
        <version>1.7.1version>
      dependency>
      
    • 添加配置

      spring.cloud.sentinel.datasource.ds.nacos.server-addr=127.0.0.1:8848
      spring.cloud.sentinel.datasource.ds.nacos.data-id=${spring.application.name}-flow-rules.json
      spring.cloud.sentinel.datasource.ds.nacos.rule-type=flow
      spring.cloud.sentinel.datasource.ds.nacos.data-type=json
      
    • 在 nacos 后台中新增 payment-service-flow-rules.json 配置文件,在文件里添加内容如下,注意 Formet 选择 JSON 格式,具体含义,见下表

      [{
          "resource": "protected-resource",
          "controlBehavior": 2,
          "count": 1,
          "grade": 1,
          "limitApp": "default",
          "strategy": 0
      }]
      
      参数 含义 选项
      grade 限流阈值类型 0 基于线程数 , 1 基于QPS
      count 限流阈值
      controlBehavior QPS流量控制中对超过阈值的流量处理手段 0 直接拒绝, 1 Warm Up, 2 匀速排队
      strategy 调用关系限流策略 0 根据调用方限流(limitApp), 1 根据调用链路入口限流, 2 具有关系的资源流量控制
      limitApp 调用来源 default 不区分调用者, {some_origin_name} 针对特定的调用者
    • 增加注解:@SentinelResource,value 就是 json里配的 protected-resource。dubbo做法也是一样

      @Override
      @RequestMapping(value = "/pay/balance", method = RequestMethod.GET)
      @SentinelResource(value = "protected-resource", blockHandler = "handleBlock")
      public Balance getBalance(@RequestParam("id") Integer id) {
          System.out.println("request: /pay/balance?id=" + id + ", sleep: " + sleep);
          return new Balance(0, 0, 0,"none");
      }
      
      // 添加 handleBlock 方法
      public Balance handleBlock(Integer id, BlockException e) {
        	return new Balance(0, 0, 0, "限流");
      }
      
    • 测试: 不断刷新 http://localhost:8001/pay/balance?id=3 接口,观察接口返回的数据

  • 使用 Sentinel 实现熔断 , 参见 springcloud-demo , 熔断是给服务消费者准备的

    • 假设在用户登录时,为了简化客户端处理,account服务的登录接口在处理成功后会调用payment服务查询余额接口获得余额信息一并返回给客户端。当payment服务严重卡顿时,我们希望登录接口不会被拖慢,而是快速失败并降级

    • 添加pom依赖,和 Sentinel之限流一样

    • 添加配置

      # 解决Read Timeout 异常
      feign.client.config.default.read-timeout=5000
      feign.client.config.default.connect-timeout=100
      
      #================配置 sentinel ==================s
      spring.cloud.sentinel.datasource.ds.nacos.server-addr=127.0.0.1:8848
      spring.cloud.sentinel.datasource.ds.nacos.data-id=${spring.application.name}-degrade-rules.json
      spring.cloud.sentinel.datasource.ds.nacos.rule-type=degrade
      spring.cloud.sentinel.datasource.ds.nacos.data-type=json
      spring.cloud.sentinel.eager=true
      #使用dubbo 的话,这个不用配置        
      feign.sentinel.enabled=true
      
    • 在 nacos 后台中新增 payment-service-degrade-rules.json 配置文件,在文件里添加内容如下,注意 Formet 选择 JSON 格式。

      [{
          "resource": "GET:http://payment-service/pay/balance",
          // 使用 dubbo时, 修改为
          //"resource": "com.example.demo.user.UserService:sayHello(java.lang.String)",
          "count": 200,
          "grade": 0,
          "timeWindow": 10
      }]
      
      • 上面配置的含义:grade=0,表示平均响应时间,当资源的平均响应时间超过阈值500毫秒(count 单位ms)之后,资源进入准降级状态。如果接下来1秒内持续进入5个请求的Read Time都持续超过这个阈值,那么在接下的时间窗口(timeWindow,10秒)之内,对这个方法的调用都会自动地熔断
      • grade=1时,表示异常比例,当资源的每秒异常总数占通过量的比值超过阈值(count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回
      • grade=2时,当资源近 1 分钟的异常数目超过阈值(count)之后会进行熔断
    • Feign:配置服务降级,当触发Read Timeout异常时,也会触发服务降级,不仅仅访问过慢时会降级

      @FeignClient(name = "payment-service", fallback = BalanceServiceFallback.class)
      public interface BalanceServiceEx extends BalanceService {
      }
      
      @Component
      public class BalanceServiceFallback implements BalanceServiceEx {
          @Override
          public Balance getBalance(Integer id) {
              return new Balance(0,0,0,"降级");
          }
      }
      
    • Dubbo:服务降级是通过Mock实现的 , 参见:dubbo-demo

      // 首先设置 mock = true
      @Reference(mock = "true" )
      private UserService userService;
      
      // 然后创建 UserServiceMock 类, 注意:要和UserService接口在同一 package 下
      package com.example.demo.user;
      
      public class UserServiceMock implements UserService {
          public UserServiceMock(){
          }
          @Override
          public String sayHello(String name) {
              System.out.print("------ 降级");
              return "降级";
          }
      }
      
    • 测试:

      • 需要启动两个 payment-service(启动1个不出现熔断,还不知道为什么), 用浏览器打开http://localhost:8081/acc/user?id=1并连续刷新6次以上, 即可出现服务熔断和降级后的返回
      • 使用 Sentinel 后台观察,更好理解
  • Sentinel 后台安装 , github

    • 下载源码并运行

      java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
      #访问: http://localhost:8080/ 
      #密码:用户名和密码都是sentinel
      
    • Client 端连接 Sentinel 后台

      # 修改payment-service 项目的配置文件,添加如下配置
      spring.cloud.sentinel.transport.dashboard=localhost:8080
      

你可能感兴趣的:(dubbo,微服务)