sentinel 服务熔断和限流

目录

sentinel 下载安装:​

初始化监控:

流量控制:

服务降级:

热点规则:

sentinel系统规则(系统自适应限流):

@SentinelResource的配置:

Sentinel服务熔断:

exceptionsToIgnore:

Sentinel服务熔断OpenFeign:

sentinel持久化规则:


  • sentinel 下载安装:

  • 访问管理页面 localhost:8080
  • 初始化监控:

  1. 建module
  2. 导入POM
    <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.ljw.springcloudstudy</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </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>
    
            <!--服务注册-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <version>0.2.1.RELEASE</version>
            </dependency>
    
        </dependencies>
    
  3. YML

    server:
      port: 8401
    
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
    #        默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
            port: 8719
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"
  4. 主启动

    @SpringBootApplication
    @EnableDiscoveryClient
    public class MainApp8401 {
        public static void main(String[] args) {
            SpringApplication.run(MainApp8401.class,args);
        }
    }
    
  5. controller

    @RestController
    public class FlowLimitController {
    
        @GetMapping("/testA")
        public String testA() {
            return "-------testA";
        }
    
        @GetMapping("/testB")
        public String testB() {
            return "-------testB";
        }
    
    }
    
  6. 执行一次访问后访问控制台(懒加载),可以看到该服务

  • 流量控制:

  1. 流控模式为直接,流控效果为快速失败时:
  2. 流控模式为关联时,当关联资源达到阈值时,限流自己;当testB访问达到阈值后,testA:
  3. 流控效果为warm up(预热)时:一开始阈值为设定阈值/cold Factor,经过预热时长后,变为设定的阈值
  4. 流控效果为排队等待时:使得请求匀速通过
  • 服务降级:

  • 首先是慢调用比例
  1.     @GetMapping("/testD")
        public String testD() {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "-------testD";
        }
    
    }
    
  2. 配置:

  3. 测试后发现熔断

  • 异常比例

  1.     @GetMapping("/testE")
        public String testE() {
    //异常
            int age=10/0;
            return "-------testE";
        }
    
  • 异常数

  1.     /**
         * 异常数
         * @return
         */
        @GetMapping("/testF")
        public String testF() {
            int age=10/0;
            return "-------testF";
        }
  2.  

  • 热点规则:

  1. 针对热点参数进行限流;

        /**
         * 热点参数限流
         *
         * @param p1
         * @param p2
         * @return
         */
        @GetMapping("/testHotKey")
    //    作为唯一标识,一般和url统一,也就是资源名称
        @SentinelResource(value = "testHotKey", blockHandler = "dealTestHotKey")
        public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                                 @RequestParam(value = "p2", required = false) String p2) {
            return "-----testHotKey";
    
        }
    //兜底方法,如果发现了热点参数,就会走这里
        public String dealTestHotKey(String p1, String p2, BlockException exception) {
    
            return "------dealTestHotKey";
    
        }
    }
    
  2. 制定热点规则:
  3. 第一个参数在一秒钟内QPS超过了阈值,则立刻进行降级处理,携带p1也会按照这个规则进行;
  4. 参数例外项:当热点参数为特殊值的时候,会有不同于其他的限流阈值;
  5. 如果是运行异常,那么@SentinelResource不负责,不走该兜底方法,@SentinelResource只负责违背控制台配置的异常。
        /**
         * 热点参数限流
         *
         * @param p1
         * @param p2
         * @return
         */
        @GetMapping("/testHotKey")
    //    作为唯一标识,一般和url统一,也就是资源名称
        @SentinelResource(value = "testHotKey", blockHandler = "dealTestHotKey")
        public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                                 @RequestParam(value = "p2", required = false) String p2) {
    //        模拟运行时异常
            int age =10/0;
            return "-----testHotKey";
    
        }
    //兜底方法,如果发现了热点参数,就会走这里
        public String dealTestHotKey(String p1, String p2, BlockException exception) {
    
            return "------dealTestHotKey/(ㄒoㄒ)/~~";
    
        }

  • sentinel系统规则(系统自适应限流):

  1. 整体维度应用入口流量进行控制
  2. 入口QPS举例:
  • @SentinelResource的配置:

  1. 按资源名称进行限流+后续处理
  2. 首先在8401中引入自定义jar包:
    <!--用于支付Entity-->
            <dependency>
                <groupId>com.ljw.springcloudstudy</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
  3. 新加一个业务类:

    @RestController
    public class ReTeLimitController {
    
        @GetMapping("/byResource")
        @SentinelResource(value = "byResource",blockHandler = "handleException")
        public CommonResult byResource(){
            return new CommonResult(200,"按资源名称进行限流测试",new Payment(2020L,"serial001"));
        }
    
        public CommonResult handleException(BlockException exception){
            return new CommonResult(444,exception.getClass().getCanonicalName()+"\t","服务不可用");
        }
    }
    
  4. 添加限流条件:

  5. 测试:

  6. 关闭服务后,流控规则会消失(非持久化);

  7. 如果没有自定义blockHandler方法,则会用系统自带的。


  8. 按资源url进行限流+后续处理

  9.     @GetMapping("/byUrl")
    //    没有自定义blockHandler方法,将会使用默认的
        @SentinelResource(value = "byUrl")
        public CommonResult byUrl(){
            return new CommonResult(200,"按资源url进行限流测试",new Payment(2020L,"serial002"));
        }
    }
  10. 测试: 


  1. 自定义限流处理+解耦:
  2. 创建自定义限流处理类:
    public class CustomerBlockHandler {
    
        public static CommonResult handlerException(BlockException exception){
            return new CommonResult(444,"自定义限流处理,global",new Payment(2020L,"serial003"));
        }
    
        public static CommonResult handlerException2(BlockException exception){
            return new CommonResult(444,"自定义限流处理,global",new Payment(2020L,"serial003"));
        }
    }
    
        @GetMapping("/customerBlockHandler")
    //调用限流处理的方法2
        @SentinelResource(value = "customerBlockHandler",
                blockHandlerClass = CustomerBlockHandler.class,
                blockHandler = "handlerException2")
        public CommonResult customerBlockHandler() {
            return new CommonResult(200, "自定义限流处理", new Payment(2020L, "serial003"));
        }
    }
  3. 需要使用资源名进行限流;
  4. 测试:

  • Sentinel服务熔断:

  1. 新建payment服务9003,9004,消费者84
  2. 服务端YML:
    server:
      port: 9003
    
    spring:
      application:
        name: nacos-payment-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"
  3. 服务端controller:
    @RestController
    public class PaymentController {
        @Value("${server.port}")
        public String serverPort;
    
        public static HashMap<Long, Payment> hashMap=new HashMap<>();
        static {
            hashMap.put(1L,new Payment(1L, UUID.randomUUID().toString()));
            hashMap.put(2L,new Payment(2L, UUID.randomUUID().toString()));
            hashMap.put(3L,new Payment(3L, UUID.randomUUID().toString()));
        }
    
        @GetMapping("/paymentSQL/{id}")
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
            Payment payment = hashMap.get(id);
            CommonResult<Payment> result = new CommonResult<>(200, "from sql,serverPort" + serverPort, payment);
            return result;
        }
    
    }
    
  4. 消费端主启动:

    @SpringBootApplication
    @EnableFeignClients
    @EnableDiscoveryClient
    public class OrderMain84 {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain84.class,args);
        }
    }
    
  5. 消费端service:

    @FeignClient(value ="nacos-payment-provider")
    public interface PaymentFeignService {
    
        @GetMapping("/paymentSQL/{id}")
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Integer id);
    }
    
  6. 消费端controller

    @RestController
    public class OrderController {
        private static final String SERVICE_NAME="nacos-payment-provider";
    
        @Resource
        private PaymentFeignService paymentFeignService;
    
        @GetMapping("/consumer/fallback/{id}")
        @SentinelResource(value = "fallback")
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
            CommonResult<Payment> result = paymentFeignService.paymentSQL(id);
            if (id == 4){
                throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
            }else if (result.getData()==null){
                throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
            }
            return result;
        }
    
    }
    
  7. fallback负责处理运行时异常,blockhandler负责配置违规;

  • 如果没有配fallback,那么将直接报错;

     

  • 只配置fallback时

        @GetMapping("/consumer/fallback/{id}")
    //    配置fallback方法
        @SentinelResource(value = "fallback",fallback = "handlerFallBack")
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
            CommonResult<Payment> result = paymentFeignService.paymentSQL(id);
            if (id == 4){
                throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
            }else if (result.getData()==null){
                throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
            }
            return result;
        }
    
        public CommonResult<Payment> handlerFallBack(@PathVariable("id") Long id,Throwable e){
            Payment payment = new Payment(id, "null");
            return new CommonResult<Payment>(444,"兜底异常handlerFallBack,exception内容"+e.getMessage(),payment);
        }

  •  只配置blockhandler,不处理运行时异常,只处理配置违规,但是可以在配置中设置异常比例和异常数来处理运行时异常;

  • 同时配置fallback和blockHandler

        @GetMapping("/consumer/fallback/{id}")
    //    配置fallback方法
        @SentinelResource(value = "fallback",fallback = "handlerFallBack",blockHandler = "blockHandler")
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
            CommonResult<Payment> result = paymentFeignService.paymentSQL(id);
            if (id == 4){
                throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
            }else if (result.getData()==null){
                throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
            }
            return result;
        }
    
        public CommonResult<Payment> handlerFallBack(@PathVariable("id") Long id,Throwable e){
            Payment payment = new Payment(id, "null");
            return new CommonResult<Payment>(444,"兜底异常handlerFallBack,exception内容"+e.getMessage(),payment);
        }
    
        public CommonResult<Payment> blockHandler(@PathVariable("id") Long id, BlockException blockException){
            Payment payment = new Payment(id, null);
            return new CommonResult<>(445,"blockHandler限流,blockException"+blockException.getMessage(),payment);
        }
    
    }
  •  

  • 同时违反配置和运行报错

     走blockHandler


  • exceptionsToIgnore:

  • 也就是发生该异常的时候,不再走fallback方法,没有降级效果;
  •     @GetMapping("/consumer/fallback/{id}")
    //    配置fallback方法
        @SentinelResource(value = "fallback",
                fallback = "handlerFallBack",
                blockHandler = "blockHandler",
    //            也就是发生该异常的时候,不再走fallback方法,没有降级效果 
                exceptionsToIgnore = {IllegalArgumentException.class})
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
            CommonResult<Payment> result = paymentFeignService.paymentSQL(id);
            if (id == 4){
                throw new IllegalArgumentException("IllegalArgumentException,非法参数异常");
            }else if (result.getData()==null){
                throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
            }
            return result;
        }
    
        public CommonResult<Payment> handlerFallBack(@PathVariable("id") Long id,Throwable e){
            Payment payment = new Payment(id, "null");
            return new CommonResult<Payment>(444,"兜底异常handlerFallBack,exception内容"+e.getMessage(),payment);
        }
    
        public CommonResult<Payment> blockHandler(@PathVariable("id") Long id, BlockException blockException){
            Payment payment = new Payment(id, null);
            return new CommonResult<>(445,"blockHandler限流,blockException"+blockException.getMessage(),payment);
        }
    
  •  


  • Sentinel服务熔断OpenFeign:

  • 消费者端YML
    server:
      port: 84
    
    spring:
      application:
        name: nacos-payment-order
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            #        默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
            port: 8719
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"
            
    #开启sentinel对feign的支持
    feign:
      sentinel:
        enabled: true
  • 主启动:

    @SpringBootApplication
    @EnableFeignClients
    @EnableDiscoveryClient
    public class OrderMain84 {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain84.class,args);
        }
    }
    
  • service:

    @FeignClient(value ="nacos-payment-provider",fallback = PaymentFeignServiceImpl.class)
    public interface PaymentFeignService {
    
        @GetMapping("/paymentSQL/{id}")
        public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
    }
    
  • 通配服务降级,处理服务端宕机,服务调用失败的情况;

    @Component
    public class PaymentFeignServiceImpl implements PaymentFeignService {
        @Override
        public CommonResult<Payment> paymentSQL(Long id) {
            return new CommonResult<Payment>(444, "服务降级访问,------PaymentFeignServiceImpl",
                    new Payment(id, "errorSerial"));
        }
    }
    

  • sentinel持久化规则:

  1. 需要导入POM
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
  2. YML

    server:
      port: 8401
    
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            #        默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
            port: 8719
              #          持久化sentinel规则的配置
          datasource:
            ds1:
              nacos:
                server-addr: localhost:8848
                dataId: cloudalibaba-sentinel-service
                groupId: DEFAULT_GROUP
                data-type: json
                rule-type: flow
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"
  3. 在nacos中新建配置:

    其中,resource:资源名称;limitApp:来源应用; grade:阀值类型,0表示线程数,1表示QPS,count:单机阈值,strategy:流控模式,0表示直接,1表示关联,2表示链路;controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;clusterMode:是否集群;

  4. 创建成功,测试:

     

    服务重启后,该规则依旧存在。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溜溜吃鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值