3.服务降级:Sentinel

0.1概念

        一个强大的流控制组件,可实现微服务的可靠性,弹性和监视。

        Sentinel以“流”为切入点,并在流控制, 流量整形,电路中断和系统自适应保护等多个领域工作,以确保微服务的可靠性和弹性。

        Sentinel具有以下功能:

                丰富的适用场景

                实时监控

                广泛的开源生态系统

                多种语言支持

        官网:https://github.com/alibaba/Sentinel

        下载:https://github.com/alibaba/Sentinel/releases

        怎么玩:服务雪崩、服务降级、服务熔断、服务限流

0.2安装

        sentinel分为两个部分:

        核心库:不依赖任何框架/库,能够运行于所有java运行时环境,同时对Dubbo/Spring Cloud等框架也有较好的支持。

        控制台(Dashboard):基于springboot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。

        安装步骤:

                本次下载sentinel-dashboard-1.7.0.jar这个版本

                运行命令,到sentinel的所在目录下:java -jar sentinel-dashboard-1.7.0.jar

                访问sentinel管理界面:http://localhost:8080/#/login,账号密码均为sentinel

0.3Sentinel的初步使用

        (1)先启动Nacos注册中心

        (2)创建Maven工程作为服务提供者(cloudalibab-sentinel-service8401)

        (3)添加Nacos和Sentinel依赖



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

         (4)application.yml

server:
  port: 8401
spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置sentinel 控制台(dashboard)地址,使8080监控8401
        port: 8719  #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
management: #暴露监控的端点
  endpoints:
    web:
      exposure:
        include: '*'

        (5)Controller

@RestController
public class FlowLimitController
{
    @GetMapping("/testA")
    public String testA() throws InterruptedException {
        return "------testA";
    }

    @GetMapping("/testB")
    public String testB() {
        return "------testB";
    }
}

(5)启动类上加@EnableDiscoveryClient

        (6)测试:

                启动Sentinel控制台、启动8401、查看sentinel控制台

                一打开是空的,因为Sentinel采用的懒加载说明,访问一次Controller即可。

0.4流控规则

3.服务降级:Sentinel_第1张图片

 3.服务降级:Sentinel_第2张图片

        流控模式

                1.直接(默认):快速失败报默认错误:Blocked by Sentinel(flow limiting)

3.服务降级:Sentinel_第3张图片

 

                        问题:直接调用默认报错信息,是否应该有我们自己的后续处理?类似fallback的兜底方法?

                2.关联:当与A关联的资源B达到阈值后,就限流A

3.服务降级:Sentinel_第4张图片

                3.链路:多个请求调用了同一个微服务

        流控效果

                1.快速失败(默认)

                2.预热(Warm UP)

3.服务降级:Sentinel_第5张图片

                        应用场景如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是为了保护系统,慢慢的把流量放进来,慢慢的把阈值恢复到原来设置的阈值

                3.排队等待

3.服务降级:Sentinel_第6张图片

 3.服务降级:Sentinel_第7张图片

0.5降级规则

        Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误。

        当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)。

        Sentinel的断路器是没有半开状态的:半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。

        降级策略

                1.RT:当1秒内持续进入5或大于5个请求,平均响应时间(秒)均超过阈值(ms),在接下来的时间窗口(s)之内,对这个方法的调用都会自动地熔断(抛出DegradeException)

                        Sentinel默认统计的RT上限是4900ms,超过此阈值都会算作4900ms,要更改的话配置:Dcsp.sentinel.statistic.max.rt=xxx

3.服务降级:Sentinel_第8张图片

                2.异常比例:当1秒内进入请求>=5,并且异常比例超过阈值之后,资源进入降级状态。不满足1秒内请求>5条件的话,还是会照常报错

                3.异常数:当资源1分钟的异常数目超过阈值之后会进行熔断。由于统计窗口是分钟级别的,若小于60秒,则结束熔断状态仍可能再进入熔断状态。所以时间窗口一定大于等于60秒

3.服务降级:Sentinel_第9张图片

0.6热点规则

        使用@SentinelResource(value="要在sentinel上配置热点规则的资源名")

        注意:@SentinelResource处理的是控制台配置的违规情况,运行出错该走异常就走异常

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey") //违背了热点key规则,就找兜底的方法,不配置blockHandler就报异常
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)
}

        根据配置的限流阈值与模式,对包含该参数的资源调用进行限流

        该配置规则:包含第一个参数时(索引从0开始,也就是p1)的请求访问超过1秒1次就限流。

        参数例外项

                上述案例演示了第一个参数p1,当QPS超过1秒1此点击后马上被限流

                特例情况:我们期望p1参数当它是某个特殊值时,它的限流值和平均不一样,假如p1等于5时,它的阈值可以达到200

0.7系统规则

        从整体维度对应用入口流量进行控制,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

0.8@SentinelResource

        按资源名称限流:把微服务关了后,流控规则消失了,是临时的

@SentinelResource(value = "byResource", blockHandler = "handleException")

        按照url地址限流:通过访问的url来限流,会返回sentinel自带默认的限流处理信息

@GetMapping("/rateLimit/byUrl") //把/rateLimit/byUrl当做资源名在控制台配置,不使用下面的byUrl
@SentinelResource(value = "byUrl")

        上面兜底方案面临的问题

                系统默认的,没有体现我们自己的业务要求

                自定义的处理方法有和业务代码耦合在一块,不直观

                每个业务代码都添加一个兜底的,代码膨胀加剧

                全局统一的处理方法没有体现

        自定义限流处理逻辑:

                (1)创建CustomerBlockHandler类用于自定义限流处理逻辑

public class CustomerBlockHandler {
    public static CommonResult handleException1(BlockException exception) {
        return new CommonResult(4444, "自定义限流处理信息....handleException---1");
    }
    public static CommonResult handleException2(BlockException exception) {
        return new CommonResult(4444, "自定义限流处理信息....handleException---2");
    }
}

                 (2)Controller使用

//自定义限流处理逻辑
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
        blockHandlerClass = CustomerBlockHandler.class, //自定义限流处理类
        blockHandler = "handlerException2") //自定义限流处理类里的哪个方法为你兜底

0.9服务熔断

        Sentinel整合ribbon+openFeign+fallback

        Ribbon

                (1)创建Maven工程为服务提供者(cloudalibaba-provider-payment9003/9004)

                (2)application.yml

server:
  port: 9003 //记得修改不同的端口
spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos注册中心地址
management:
  endpoints:
    web:
      exposure:
        include: '*'

                (3)启动类上加@EnableDiscoveryClient

                (4)创建Maven工程为服务消费者(cloudalibaba-consumer-nacos-order84)

                (5)application.yml

server:
  port: 84
spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #服务注册中心
    sentinel:
      transport:
        dashboard: localhost:8080 #sentinel控制台地址,使8080监控84
        port: 8719
service-url:
  nacos-user-service: http://nacos-payment-provider #去nacos注册中心访问nacos-payment-provider微服务

                (6)启动类上加@EnableFeignClients、@EnableDiscoveryClient

                (7)Controller

@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}) //exceptionsToIgnore忽略的异常,报了该异常不再兜底 
public CommonResult fallback(@PathVariable Long id) {
    CommonResult 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);
}

                (8)测试: 没有配置@SentinelResource,给用户error页面

                                配置了fallback和blockHandler都配置,blockhandler最大。

        openFeign

                (1)openfeign只跟消费侧有关,修改84

                (2)假如openFeign依赖


    org.springframework.cloud
    spring-cloud-starter-openfeign

                 (3)在yml激活Sentinel对openFeign的支持

feign:
  sentinel:
    enabled: true

                 (3)测试84调用9003,此时故意关闭9003,84端自动降级,不会被耗死

你可能感兴趣的:(SpringCloud,alibaba,spring,cloud,alibaba)