SpringCloud Alibaba - Sentinel篇

SpringCloud Alibaba - Sentinel篇

码农世界 2024-05-30 后端 94 次浏览 0个评论

一、Sentinel快速入门


SpringCloud Alibaba - Sentinel篇

Sentinel官网地址:https://sentinelguard.io/zh-cn/index.html

Sentinel项目地址:https://github.com/alibaba/Sentinel

Sentinel是阿里巴巴开源的一款微服务流量治理组件,主要以流量为切入点,从流量限流、熔断降级、系统负载保护等多个维度来帮助开发者保障微服务的稳定性。(对标产品:Springcloud Hystrix 豪猪哥)

Sentinel分为两个部分:

  • 核心库(Java客户端):该jar包不依赖任何框架,能够运行于 Java 8 及以上版本,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard):相当于是Sentinel框架的管理中心,可以通过图形化界面对Sentinel进行配置、监控(可以对服务的流量、请求、响应等指标进行监控)等操作,从而更好地保障应用的稳定性和可靠性。

    SpringCloud Alibaba - Sentinel篇

    两款熔断框架对比:

    功能SentinelHystrix(豪猪哥)
    线程隔离信号量隔离线程池隔离/信号量隔离
    熔断策略基于慢调用比例或异常比例基于异常比例
    限流基于QPS,支持流量整形有限的支持
    Fallback支持支持
    控制台开箱即用,可配置规则、查看秒级监控、机器发现等不完善
    配置方式基于控制台,重启后失效基于注解或配置文件,永久生效

    1. 启动sentinel-dashboard控制台


    通过可视化更方便操作Sentinel。

    1、下载sentinel-dashboard的jar包:https://github.com/alibaba/Sentinel/releases/tag/1.8.6

    SpringCloud Alibaba - Sentinel篇

    2、使用命令行运行jar包的方式启动控制台:(或者构建镜像丢到容器中启动)

    java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
    

    参数介绍:

    • -Dserver.port=8090:指定Sentinel控制台程序的端口为8090。

    • -Dcsp.sentinel.dashboard.server=localhost:8090:Sentinel控制台的访问地址,客户端会自动向该地址发送心跳包。

    • -Dproject.name=sentinel-dashboard:指定Sentinel控制台程序显示的名称。

    • 文档地址:https://github.com/alibaba/Sentinel/wiki/%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E9%A1%B9

      SpringCloud Alibaba - Sentinel篇

      3、访问sentinel的控制台:http://localhost:8090/,默认账号/密码:都是sentinel。

      SpringCloud Alibaba - Sentinel篇

      登录成功后,便可查看控制台内部信息,默认会监控sentinel-dashboard服务本身:

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      2. 构建微服务环境


      数据库准备:

      CREATE DATABASE cloud_demo DEFAULT CHARACTER SET utf8mb4;
      use cloud_demo;
      DROP TABLE IF EXISTS `tb_user`;
      CREATE TABLE `tb_user`  (
        `id` bigint(20) NOT NULL AUTO_INCREMENT,
        `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
        `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
        PRIMARY KEY (`id`) USING BTREE,
        UNIQUE INDEX `username`(`username`) USING BTREE
      ) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
      INSERT INTO `tb_user` VALUES (1, '潘掌柜', '黑龙江省牡丹江市');
      INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
      INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
      INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
      INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
      INSERT INTO `tb_user` VALUES (6, 'kunkun', '山东省青岛市');
      DROP TABLE IF EXISTS `tb_order`;
      CREATE TABLE `tb_order`  (
        `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
        `user_id` bigint(20) NOT NULL COMMENT '用户id',
        `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
        `price` bigint(20) NOT NULL COMMENT '商品价格',
        `num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
        PRIMARY KEY (`id`) USING BTREE,
        UNIQUE INDEX `username`(`name`) USING BTREE
      ) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
      INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
      INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
      INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
      INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
      INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
      INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
      INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
      INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);
      

      SpringCloud Alibaba - Sentinel篇

      2.1 创建父工程

      springboot版本2.7.12,springcloud版本2021.0.3。

      创建maven工程,删除src目录,并向pom文件中引入一些依赖:

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      
      
          4.0.0
          cn.z3inc
          sentinel-demo
          pom
          1.0
          
          
              org.springframework.boot
              spring-boot-starter-parent
              2.7.12
               
          
          
              8
              8
              UTF-8
              1.18.20
              2021.0.3
              2021.0.4.0
              3.4.3
              5.8.11
              8.0.23
          
          
          
              
                  
                  
                      org.springframework.cloud
                      spring-cloud-dependencies
                      ${spring-cloud.version}
                      pom
                      import
                  
                  
                  
                      com.alibaba.cloud
                      spring-cloud-alibaba-dependencies
                      ${spring-cloud-alibaba.version}
                      pom
                      import
                  
                  
                  
                      mysql
                      mysql-connector-java
                      ${mysql.version}
                  
                  
                  
                      com.baomidou
                      mybatis-plus-boot-starter
                      ${mybatis-plus.version}
                  
                  
                  
                      cn.hutool
                      hutool-all
                      ${hutool.version}
                  
              
          
          
              
              
                  org.projectlombok
                  lombok
                  ${org.projectlombok.version}
              
              
              
                  org.springframework.boot
                  spring-boot-starter-test
                  test
              
          
         
          
              
              
                  org.apache.maven.plugins
                  maven-surefire-plugin
                  
                      true
                  
              
          
      
          
      
      

      2.2 创建用户微服务

      1、创建用户模块

      SpringCloud Alibaba - Sentinel篇

      2、引入依赖:

      
      
          4.0.0
          
              cn.z3inc
              sentinel-demo
              1.0
          
          user-service
          
              8
              8
              UTF-8
          
          
              
              
                  com.alibaba.cloud
                  spring-cloud-starter-alibaba-nacos-discovery
              
              
              
                  org.springframework.boot
                  spring-boot-starter-test
              
              
              
                  org.springframework.boot
                  spring-boot-starter-web
              
              
              
                  mysql
                  mysql-connector-java
              
              
              
                  com.baomidou
                  mybatis-plus-boot-starter
              
              
              
                  org.projectlombok
                  lombok
              
              
              
                  cn.hutool
                  hutool-all
              
          
          
          
              
                  
                      org.springframework.boot
                      spring-boot-maven-plugin
                  
              
          
      
      

      3、编写application.yml文件配置:

      server:
        port: 9001
      spring:
        application:
          name: user-service #服务名称
        cloud:
          nacos:
            # nacos注册中心配置
            discovery:
              server-addr: 127.0.0.1:8848 #nacos服务器地址
        # 数据库配置
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/cloud_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
      # mp配置
      mybatis-plus:
        mmapper-locations: classpath:mapper/*.xml #mapper配置文件存放路径
        type-aliases-package: cn.z3inc.user.pojo # 类型别名(实体类所在包)
        configuration:
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #配置标准sql输出
          map-underscore-to-camel-case: true #开启驼峰映射
      #日志级别
      logging:
        level:
          cn.z3inc: debug
        pattern:
          dateformat: MM-dd HH:mm:ss:SSS # 格式化输出日期
      

      4、编写启动类:

      @SpringBootApplication
      @MapperScan("cn.z3inc.user.mapper")
      public class UserServiceApplication {
          public static void main(String[] args) {
              SpringApplication.run(UserServiceApplication.class, args);
          }
      }
      

      5、编写业务:

      实体类:

      package cn.z3inc.user.pojo;
      import lombok.Data;
      @Data
      public class User {
          private Long id;
          private String username;
          private String address;
      }
      

      mapper接口:

      package cn.z3inc.user.mapper;
      import cn.z3inc.user.pojo.User;
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import org.apache.ibatis.annotations.Mapper;
      @Mapper
      public interface UserMapper extends BaseMapper {
          
      }
      

      service接口:

      package cn.z3inc.user.service;
      import cn.z3inc.user.pojo.User;
      import com.baomidou.mybatisplus.extension.service.IService;
      public interface UserService extends IService {
      }
      
      package cn.z3inc.user.service.impl;
      import cn.z3inc.user.mapper.UserMapper;
      import cn.z3inc.user.pojo.User;
      import cn.z3inc.user.service.UserService;
      import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import org.springframework.stereotype.Service;
      @Service
      public class UserServiceImpl extends ServiceImpl implements UserService {
      }
      

      controller:

      package cn.z3inc.user.controller;
      import cn.z3inc.user.pojo.User;
      import cn.z3inc.user.service.UserService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.*;
      @RestController
      @RequestMapping("/user")
      public class UserController {
          @Autowired
          private UserService userService;
          /**
           * 根据ID获取用户信息
           *
           * @param id 用户ID
           * @return
           */
          @GetMapping("/{id}")
          public User findById(@PathVariable("id") Long id) {
              return userService.getById(id);
          }
          /**
           * 修改用户信息
           *
           * @param user 用户信息
           */
          @PutMapping("/update")
          public void updateUser(@RequestBody User user) {
              userService.updateById(user);
          }
          /**
           * 根据ID删除用户
           *
           * @param id
           * @return
           */
          @DeleteMapping("/{id}")
          public void deleteUser(@PathVariable("id") Long id) {
              userService.removeById(id);
          }
          /**
           *  新增用户
           * @param user
           */
          @PostMapping("/save")
          public void saveUser(@RequestBody User user) {
              userService.save(user);        
          }
      }
      

      SpringCloud Alibaba - Sentinel篇

      6、启动nacos、用户微服务测试

      .\startup.cmd -m standalone
      

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      2.3 创建订单微服务

      1、创建订单模块

      SpringCloud Alibaba - Sentinel篇

      2、引入依赖:

      
      
          4.0.0
          
              cn.z3inc
              sentinel-demo
              1.0
          
          order-service
          
              8
              8
              UTF-8
          
          
              
              
                  org.springframework.cloud
                  spring-cloud-starter-openfeign
              
              
              
                  org.springframework.cloud
                  spring-cloud-starter-loadbalancer
              
              
              
                  com.alibaba.cloud
                  spring-cloud-starter-alibaba-nacos-discovery
              
              
              
                  org.springframework.boot
                  spring-boot-starter-test
              
              
              
                  org.springframework.boot
                  spring-boot-starter-web
              
              
              
                  mysql
                  mysql-connector-java
              
              
              
                  com.baomidou
                  mybatis-plus-boot-starter
              
              
              
                  org.projectlombok
                  lombok
              
              
              
                  cn.hutool
                  hutool-all
              
          
          
          
              
                  
                      org.springframework.boot
                      spring-boot-maven-plugin
                  
              
          
      
      

      3、编写application.yml配置:

      server:
        port: 9001
      spring:
        application:
          name: user-service #服务名称
        cloud:
          nacos:
            # nacos注册中心配置
            discovery:
              server-addr: 127.0.0.1:8848 #nacos服务器地址
        # 数据库配置
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/cloud_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
      # mp配置
      mybatis-plus:
        mmapper-locations: classpath:mapper/*.xml #mapper配置文件存放路径
        type-aliases-package: cn.z3inc.order.pojo # 类型别名(实体类所在包)
        configuration:
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #配置标准sql输出
          map-underscore-to-camel-case: true #开启驼峰映射
        global-config:
          db-config:
            id-type: auto # 主键策略
            table-prefix: tb_ # 表名前缀配置
      #日志级别
      logging:
        level:
          cn.z3inc: debug
        pattern:
          dateformat: MM-dd HH:mm:ss:SSS # 格式化输出日期
      

      4、编写启动类:

      package cn.z3inc.order;
      import org.mybatis.spring.annotation.MapperScan;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      @EnableFeignClients(basePackages = "cn.z3inc.order.feign") //开启feign远程调用
      @SpringBootApplication
      @MapperScan("cn.z3inc.order.mapper")
      public class OrderServiceApplication {
          public static void main(String[] args) {
              SpringApplication.run(OrderServiceApplication.class, args);
          }
      }
      

      5、编写业务:

      实体类:

      //用户实体
      @Data
      public class User {
          private Long id;
          private String username;
          private String address;
      }
      // 订单实体
      @Data
      public class Order {
          private Long id;
          private String name;
          private Long price;
          private Integer num;
          private Long userId;
          @TableField(exist = false) // 排除数据表中不存在的字段
          private User user;
      }
      

      mapper接口:

      package cn.z3inc.order.mapper;
      import cn.z3inc.order.pojo.Order;
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import org.apache.ibatis.annotations.Mapper;
      @Mapper
      public interface OrderMapper extends BaseMapper {
      }
      

      service接口:

      package cn.z3inc.order.service;
      import cn.z3inc.order.pojo.Order;
      import com.baomidou.mybatisplus.extension.service.IService;
      public interface OrderService extends IService {
          //根据id查订单
          Order findById(Long id);
      }
      

      feign接口:

      package cn.z3inc.order.feign;
      import cn.z3inc.order.pojo.User;
      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      /**
       *  用户服务Feign接口
       */
      @FeignClient("user-service")//指定要调用的服务名称
      public interface UserClient {
          /*
              主要是基于SpringMVC的注解来声明远程调用的信息,比如:
                  - 服务名称:userservice
                  - 请求方式:GET
                  - 请求路径:/user/{id}
                  - 请求参数:Long id
                  - 返回值类型:User
           */
          // 定义远程调用方法
          // 通过id查用户
          @GetMapping("/user/{id}") //调用对应controller的方法路径
          User findById(@PathVariable("id") Long id);// @PathVariable注解一定要指定参数名称,否则会报错
      }
      

      service接口实现类:

      @Service
      public class OrderServiceImpl extends ServiceImpl implements OrderService {
          @Autowired
          private UserClient userClient;
          @Override
          public Order findById(Long id) {
              Order order = super.getById(id);
              User user = userClient.findById(order.getUserId());//微服务远程调用
              order.setUser(user);
              return order;
          }
      }
      

      controller:

      package cn.z3inc.order.controller;
      import cn.z3inc.order.pojo.Order;
      import cn.z3inc.order.service.OrderService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.*;
      @RestController
      @RequestMapping("/order")
      public class OrderController {
          @Autowired
          private OrderService orderService;
          @GetMapping("/{orderId}")
          public Order findById(@PathVariable("orderId") Long orderId) {
              return orderService.findById(orderId);
          }
      }
      

      6、测试:

      SpringCloud Alibaba - Sentinel篇

      2.4 搭建网关微服务

      1、创建网关模块

      SpringCloud Alibaba - Sentinel篇

      2、引入依赖:

      
          
          
              org.springframework.cloud
              spring-cloud-starter-gateway
          
          
          
              org.springframework.cloud
              spring-cloud-starter-loadbalancer
          
          
          
              com.alibaba.cloud
              spring-cloud-starter-alibaba-nacos-discovery
          
      
      

      3、修改application.yml配置:

      server:
        port: 10010 # 网关的服务端口
      spring:
        application:
          name: gateway # 服务名称
        cloud:
          nacos:
            server-addr: localhost:8848 # nacos服务地址
          # 网关的配置
          gateway:
            # 跨域配置
            globalcors:
              cors-configurations:
                '[/**]':
                  allowed-origin-patterns: "*"
                  allowed-headers: "*"
                  allow-credentials: true
                  allowed-methods:
                    - GET
                    - POST
                    - DELETE
                    - PUT
                    - OPTION
            # 网关路由配置        
            routes: 
              - id: user-service # 路由id    
                uri: lb://user-service # 路由地址
                predicates: # 路由断言(匹配规则)
                  - Path=/user/** 
              - id: order-service
                uri: lb://order-service
                predicates:
                  - Path=/order/**
      

      4、编写启动类:

      package cn.z3inc.gateway;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      @SpringBootApplication
      public class GatewayApplication {
          public static void main(String[] args) {
              SpringApplication.run(GatewayApplication.class, args);
          }
      }
      

      SpringCloud Alibaba - Sentinel篇

      5、测试:

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      3. 整合Sentinel


      向订单微服中引入sentinel依赖,并连接sentinel-dashboard控制台进行监控。

      1、引入sentinel依赖:

      
      
          com.alibaba.cloud 
          spring-cloud-starter-alibaba-sentinel
      
      

      2、修改订单服务的application.yml文件,添加sentinel控制台配置:

      spring:
        cloud: 
          sentinel:
            transport:
              dashboard: localhost:8090 #控制台地址
            http-method-specify: true #开启请求方式前缀  
      

      SpringCloud Alibaba - Sentinel篇

      3、重启订单微服务

      4、访问订单微服务接口:http://localhost:9002/order/102

      5、访问sentinel-dashboard控制台,查看订单服务请求资源:http://localhost:8090

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      簇点链路:就是项目内的调用链路。链路中被Sentinel监控的每个接口就是一个资源。默认情况下Sentinel会监控SpringMVC的每一个Endpoint(http接口)。限流、熔断等都是针对簇点链路中的资源设置的,而资源名默认就是接口的请求路径。

      二、请求限流


      请求限流:限制访问接口的请求的并发量,避免服务因流量激增出现故障。

      也是在sentinel控制台中配置,点击指定簇点链路后面的流控按钮,便可做限流处理:

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      使用 JMeter做压测:

      (1)为测试计划创建线程组

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      (2)为线程组添加http取样器:

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      (3)为http取样器添加监听报告:

      SpringCloud Alibaba - Sentinel篇

      (4)为http取样器添加查看结果树:

      SpringCloud Alibaba - Sentinel篇

      (5)执行测试

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      最后控制台查看监控结果:

      SpringCloud Alibaba - Sentinel篇

      可以看出这个接口,通过的QPS为6,拒绝的QPS为4,符合我们的预期。

      三、线程隔离


      限流可以降低服务器压力,尽量减少因并发流量引起的服务故障的概率,但并不能完全避免服务故障。一旦某个服务出现故障,我们必须隔离对这个服务的调用,避免发生雪崩。

      线程隔离:也叫做舱壁模式,模拟船舱隔板的防水原理。通过限定每个业务使用的线程数量,将故障业务隔离,避免故障扩散。(好处:即使服务崩了损失一部分线程,也不会影响到整个 tomcat 的资源)

      SpringCloud Alibaba - Sentinel篇

      1. OpenFeign整合Sentinel


      对订单服务的FeignClient接口做线程隔离。

      修改订单服务的application.yml文件,配置开启Feign的sentinel功能:

      feign:
        sentinel:
          enabled: true # 开启feign对sentinel的支持
      

      SpringCloud Alibaba - Sentinel篇

      重启订单服务,可以看到查询用户的FeignClient自动变成了一个簇点资源:

      SpringCloud Alibaba - Sentinel篇

      2. 配置线程隔离


      给查询用户feign接口的簇点资源配置并发线程数:(最多使用5个线程)

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      SpringCloud Alibaba - Sentinel篇

      执行JMeter测试脚步,每秒发送100个请求:

      SpringCloud Alibaba - Sentinel篇

      测试结果如下:

      SpringCloud Alibaba - Sentinel篇

      四、服务熔断


      服务熔断:由 断路器 统计请求的异常比例或慢调用比例,如果超出阈值则会 熔断 该业务,则拦截该接口的请求。熔断期间,所有请求快速失败,全都走fallback降级逻辑,避免影响到当前服务。(Hystrix豪猪哥的做法:如果feign接口调不通,那就走feign接口实现类的逻辑,避免服务雪崩)

      SpringCloud Alibaba - Sentinel篇

      1. 编写降级逻辑


      跟豪猪哥的用法类似。

      触发限流或熔断后的请求不一定要直接报错,也可以返回一些默认数据或者友好提示,用户体验会更好。

      通常为FeignClient编写失败后的降级逻辑有两种方式:

      • 方式一:FallbackClass,无法对远程调用的异常做处理。
      • 方式二:FallbackFactory,可以对远程调用的异常做处理(推荐使用)。

        1、为订单服务的UserClient定义降级处理类,实现FallbackFactory接口。

        package cn.z3inc.order.fallback;
        import cn.z3inc.order.feign.UserClient;
        import cn.z3inc.order.pojo.User;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.cloud.openfeign.FallbackFactory;
        /**
         * UserClient降级处理类
         *
         */
        @Slf4j
        @Configuration
        public class UserClientFallback implements FallbackFactory {
            // 定义userclient降级逻辑
            @Override
            public UserClient create(Throwable cause) {
                return new UserClient(){
                    @Override
                    public User findById(Long id) { 
                        log.error("远程调用UserClient#findById方法出现异常,参数:{}", id, cause);
                        return new User();
                    }
                };
            }
        }
        

        SpringCloud Alibaba - Sentinel篇

        2、创建一个配置类,把UserClientFallback注册为一个Bean:

        package cn.z3inc.order.config;
        import cn.z3inc.order.fallback.UserClientFallback;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.context.annotation.Bean;
        @Slf4j
        public class DefaultFeignConfig {
            
            @Bean
            public UserClientFallback userClientFallback() {
                return new UserClientFallback();
            }
        }
        

        3、在UserClient中配置刚才创建的降级处理类:

        /**
         *  用户服务Feign接口
         */
        @FeignClient(value = "user-service", //指定要调用的服务名称
                configuration = DefaultFeignConfig.class, // 指定Feign的配置类
                fallbackFactory = UserClientFallback.class // 指定回退工厂类
        )
        public interface UserClient {
        

        SpringCloud Alibaba - Sentinel篇

        4、重启订单服务,将用户服务停掉&测试:

        SpringCloud Alibaba - Sentinel篇

        2. 服务熔断


        当远程调用的服务挂掉后,直接走降级逻辑,避免影响到当前服务。也就是将feign接口进行熔断。当远程调用服务恢复正常后,再允许调用该接口。这其实就是断路器的工作模式了。

        Sentinel中的断路器不仅可以统计某个接口的慢请求比例,还可以统计异常请求比例。当这些比例超出阈值时,就会熔断该接口,即拦截访问该接口的一切请求,降级处理;当该接口恢复正常时,再放行对于该接口的请求。

        断路器的工作状态切换有一个状态机来控制:

        SpringCloud Alibaba - Sentinel篇

        状态机包括三个状态:

        • closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则切换到open状态
        • open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。Open状态持续一段时间后会进入half-open状态
        • half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。
          • 请求成功:则切换到closed状态
          • 请求失败:则切换到open状态

            我们可以在控制台通过点击簇点链路后的熔断按钮来配置熔断策略:(持久化需要写到nacos配置文件里)

            SpringCloud Alibaba - Sentinel篇

            SpringCloud Alibaba - Sentinel篇

            这种是按照慢调用比例来做熔断,上述配置的含义是:

            • RT超过200毫秒的请求调用就是慢调用
            • 统计最近1000ms内的最少5次请求,如果慢调用比例不低于0.5,则触发熔断
            • 熔断持续时长20s

              使用jmeter测试:

              SpringCloud Alibaba - Sentinel篇

              SpringCloud Alibaba - Sentinel篇

转载请注明来自码农世界,本文标题:《SpringCloud Alibaba - Sentinel篇》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,94人围观)参与讨论

还没有评论,来说两句吧...

Top