0
点赞
收藏
分享

微信扫一扫

Day11-SpringCloud alibaba服务降级熔断框架Sentinel (笔记全)

GG_lyf 2022-01-07 阅读 28

文章目录

Sentinel介绍及下载安装

Sentinel-features-overview

下载安装可视端

启动

创建项目

  • pom.xml

            <!--SpringCloud ailibaba nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
            <!--SpringCloud ailibaba sentinel -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <!--openfeign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
  • yaml

    server:
      port: 8401
    
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery: # http://1.116.182.96:8888/files
            server-addr: localhost:8848 #Nacos服务注册中心地址
        sentinel:
          transport:
            dashboard: localhost:8080 #配置Sentinel dashboard地址
            port: 8719
          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: '*'
    
    feign:
      sentinel:
        enabled: true # 激活Sentinel对Feign的支持
    
    
  • 主启动类

    @EnableDiscoveryClient
    @SpringBootApplication
    public class MainApp8401
    {
        public static void main(String[] args) {
            SpringApplication.run(MainApp8401.class, args);
        }
    }
    
    
  • Controller测试类

    package com.atguigu.springcloud.alibaba.controller;
    
    import com.alibaba.csp.sentinel.annotation.SentinelResource;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * @auther zzyy
     * @create 2020-02-24 16:26
     */
    @RestController
    @Slf4j
    public class FlowLimitController
    {
        @GetMapping("/testA")
        public String testA()
        {
            return "------testA";
        }
    
        @GetMapping("/testB")
        public String testB()
        {
            log.info(Thread.currentThread().getName()+"\t"+"...testB");
            return "------testB";
        }
    
    
        @GetMapping("/testD")
        public String testD()
        {
    //        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
    //        log.info("testD 测试RT");
    
            log.info("testD 异常比例");
            int age = 10/0;
            return "------testD";
        }
    
        @GetMapping("/testE")
        public String testE()
        {
            log.info("testE 测试异常数");
            int age = 10/0;
            return "------testE 测试异常数";
        }
    
        @GetMapping("/testHotKey")
        @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
        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 deal_testHotKey (String p1, String p2, BlockException exception)
        {
            return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
        }
    
    }
    
    
  • 访问 http://localhost:8401/testB 看看控制台实时监控

image-20220106113510870

Sentinel流控规则

image-20220106114105601

image-20220106114428849

流控模式-----直接

image-20220106114617589

image-20220106114642362

每秒三下触发默认限流规则 抛出异常

流控模式-----关联

image-20220106115313850

测试:

image-20220106115534159

PostMan中新建多线程集合组

image-20220106164744324

后台运行 /testB 前台访问 /testA

效果: (被限流)

image-20220106164828302

流控模式—–链路

image-20220106165030947

Sentinel降级规则

熔断策略

Sentinel热点规则

返回自定义异常显示

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    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 deal_testHotKey (String p1, String p2, BlockException exception)
    {
        return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
    }

设定热点规则

image-20220106170458989

image-20220106171507571

关于该资源内部出错

Sentinel系统规则(了解即可)

image-20220106171728394

@SentinelResource

关键属性:

  • value:资源名称,必需项(不能为空)

  • fallback:fallback函数名称,可选项,用于在抛出异常的时候提供 fallback处理逻辑。fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback函数签名和位置要求: 返回值类型必须与原函数返回值类型一致;方法参数列表需要和原函数一致,或者可以额外多一个 Throwable类型的参数用于接收对应的异常。

     @GetMapping("/rateLimit/byUrl")
        @SentinelResource(value = "byUrl",fallback ="runTimeException")
        public CommonResult byUrl()
        {
    
            int age = 10/0;
    
            return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
        }
        public CommonResult runTimeException(Throwable exception) //这里不能用Exception
        {
    
            return new CommonResult(666,exception.getClass().getCanonicalName()+"\t 运行时异常");
        }
    
  • blockHandler:实现处理函数,该函数的传参必须与资源点的传参一样,并且最后加上BlockException异常参数;同时,返回类型也必须一样。

        @GetMapping("/byResource")
        @SentinelResource(value = "byResource",blockHandler = "handleException" )
        public CommonResult byResource()
        {
            return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
        }
    
        public CommonResult handleException(BlockException exception)
        {
            return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
        }
    
  • blockHandlerClass: 自定义限流处理类

  • fallbackClass: 自定义异常类

同时启用blockHander 和 fallback

整合Ribbon+openFeign+fallback实现服务熔断

  • 客户端引入依赖

            <!--SpringCloud openfeign -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <!--SpringCloud ailibaba nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!--SpringCloud ailibaba sentinel -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
    
  • 主启动类

    @EnableDiscoveryClient
    @SpringBootApplication
    @EnableFeignClients
    public class OrderNacosMain84
    {
        public static void main(String[] args) {
            SpringApplication.run(OrderNacosMain84.class, args);
        }
    }
    
    
  • 配置RestTemplate 负载均衡

    @Configuration
    public class ApplicationContextConfig
    {
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate()
        {
            return new RestTemplate();
        }
    }
    @Configuration
    public class ApplicationContextConfig
    {
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate()
        {
            return new RestTemplate();
        }
    }
    
    
  • Controller测试

    //测试RestTemplate
        @Value("${service-url.nacos-user-service}")
        public String SERVICE_URL;
    
        @GetMapping("/consumer2/paymentSQL/{id}")
        public CommonResult<Payment> paymentSQ2(@PathVariable("id") Long id)
        {
            return restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class);
        }
    

image-20220107022504883

image-20220107022518753

可以看见是轮询访问服务端

 ```java
 //测试OpenFeign
    //==================OpenFeign
     @Resource
     private PaymentService paymentService;
 
     @GetMapping(value = "/consumer/paymentSQL/{id}")
     public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
     {
         return paymentService.paymentSQL(id);
 
     }
 =============================================================================
     //service
    @FeignClient(value = "${service-url.nacos-user-service}",fallback = PaymentFallbackService.class)
 public interface PaymentService
 {
     @GetMapping(value = "/paymentSQL/{id}")
     public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
 }
  
 ```

这里就不截图了 同样效果

  • 实现熔断

       @RequestMapping("/consumer/fallback/{id}")
        //@SentinelResource(value = "fallback") //没有配置
        //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
        //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
        @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
                exceptionsToIgnore = {IllegalArgumentException.class})
        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 ("IllegalArgumentException,非法参数异常....");
            }else if (result.getData() == null) {
                throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
            }
    
            return result;
        }
        //本例是fallback
        public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
            Payment payment = new Payment(id,"null");
            return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
        }
        //本例是blockHandler
        public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
            Payment payment = new Payment(id,"null");
            return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
        }
    
  • 关闭远程服务试试

    image-20220107023947406

持久化配置

image-20220107024214451

实现步骤

  • <!--SpringCloud ailibaba sentinel-datasource-nacos -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    
     
    
  • yaml

    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: IP:8848 #Nacos服务注册中心地址
        sentinel:
          transport:
            dashboard: localhost:8080 #配置Sentinel dashboard地址
            port: 8719
          datasource:
            ds1:
              nacos:
                server-addr: IP:8848
                dataId: cloudalibaba-sentinel-service
                groupId: DEFAULT_GROUP
                data-type: json
                rule-type: flow
    
  • 在Nacos可视化面板添加规则

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

image-20220107024706012

image-20220107025355371

成功!

举报

相关推荐

0 条评论