学习 spring-cloud-aibaba第五篇,服务容错 Sentinel 上篇


特别声明:整理自慕课网大目师兄的微服务视频,链接: https://coding.imooc.com/learn/list/358.html
前情提要:nacos上注册了 content-centeruser-center两个服务, content-center使用 Feign调用 user-center服务,使用 Ribbon做负载均衡, sentinel实现服务容错! sentinel使用简单,精通就难了,可以配置的选择很多,可以操作的余地也很足!

1.为什么需要服务容错?

1.1 雪崩效应

在这里插入图片描述
雪崩效应(级联故障):如图所示,C,D服务调用B服务,B服务调用A服务,如果A服务突然发生故障,那么B服务调用A服务就得不到返回,直到请求超时,在超时之前的那段时间内,请求一直在等待,简直欲穿秋水,一个请求就是一个线程,线程一直处于阻塞状态,会一直占用服务器的资源,比如内存,cpu;如果B的并发很高,这样阻塞的线程很多,那么B服务器再也没有资源去创建新的线程,于是B也挂了,然后C,D服务又请求不到B服务了…然后C,D服务也挂了。因为A服务的故障,BCD没有做任何处理,都挂了,这就是雪崩效应

1.2 什么是服务容错

我的理解就是服务容错的目的就是保护自己服务的正常运行。比如B服务碰到上面那种请求等待导致线程太多的时候,我就限流,某某请求的线程不得超过10个,超过10个就不再接受新的请求,直接返回被限流错误提示,这样B服务就不会因为太多线程耗尽内存而亡了

1.3 常见的容错方案

  • 超时
    最容易想到的方案,把请求时间设置的很短,这样线程释放的足够快,B服务就不会那么容易被耗死了
    体现思想:天下武功,唯快不破!
  • 限流
    我们经过测试,发现某个请求能承受的最大QPS(每秒查询率)是1000,那我们就把这个请求的QPS阈值设置成800,超过了这个阈值,请求直接返回被限流的错误(限流功能仅仅是Setinel众多功能当中的一个)
    体现思想:世相万变,我心不变,他弱由他弱,清风拂山岗,他强由他强,明月照大江!
  • 仓壁模式
    创造很多的隔断间,每个隔断间都有一个自己的线程池,你自己的线程池满了,后续请求按照线程池的规则排队,还是啥的就行了,不会影响到其它的隔断间。可以把Controller当作隔断间,也可以是其它的,反正就是这个意思
    体现思想:不把鸡蛋放一个篮子里!
  • 断路器模式
    检测一定时间内的错误率,错误数,比如5秒之内错误率,错误次数,达到某个阈值,就认为B服务所调用的A服务挂了,我就跳闸,就不会堆积那么多线程等待了,然后在10秒之后(称作断路器时间窗口),断路器变成半开状态,此状态向A再发送仅仅一次请求,如果这次请求又失败了,我再跳闸,默默的等10秒(断路器时间窗口,不是非得10秒,我只是举例子,值自己可以设定),断路器又变成半开状态,再次向A发送一次请求,如果这次请求成功了,断路器就彻底恢复,闸彻底闭合(断路器模式也是Setinel众多功能当中的一个)
    体现思想:可以自我修复的高级保险丝!

2.部署Sentinel控制台

Sentinelnacos有点像,都有个控制台

2.1 下载Sentinel.jar包

2.2 运行Sentinel.jar包

Sentinel的端口是8080,所以你得把8080端口先空出来

一般执行下面这个命令就行了,不过窗口关闭,服务也会停掉

 java -jar sentinel-dashboard-1.6.3.jar

这个命令是linux系统后台窗口运行的,窗口关闭,服务也不会停止

nohup java -jar sentinel-dashboard-1.6.3.jar &

2.3 登录Sentinel控制台

ip+端口号访问服务,用户名和密码都是:sentinel,我用本地的sentinel
在这里插入图片描述
在这里插入图片描述

3.微服务整合Sentinel

依旧三板斧

3.1 加依赖

sentinel建立在springbootactuator组件上

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

3.2 写注解

暂无注解

3.3 写配置

指定sentinel 控制台地址

spring:
  cloud:
    sentinel:
      transport:
        # 指定 sentinel 控制台地址
        dashboard: localhost:8080
management:
  endpoints:
    web:
      exposure:
        # 暴露出所有actuator监控的端点
        include: '*'

3.4 懒加载

sentinel是懒加载的,所以得访问一下content-center服务的http://localhost:8081/poem/testRibbon接口,再刷新Sentinel控制台,就能看到content-center
在这里插入图片描述

4.簇点链路

  • 给资源添加规则的入口
  • 被请求的路径,都称作资源,会在簇点链路里显示出来,没有被请求的就不会显示出来
    在这里插入图片描述

5.流控规则限流

5.1 参数解释

在这里插入图片描述

参数名含义
资源名即限流规则的作用对象
针对来源流控针对的调用来源(服务级别),若为 default 则不区分调用来源
阈值类型QPS(每秒查询率) 或并发线程数(感觉这个就是仓壁模式)
单机阈值限流阈值,超过这个值就执行流控规则
流控模式直接,关联,链路
流控效果直接拒绝、Warm Up、匀速排队
是否集群这个功能好像还不能用

比较难以理解的就是流控模式流控效果

5.1.1 流控模式

基于调用关系的流量控制

  • 直接
    直接针对资源本身
  • 关联
    当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。当关联的资源达到阈值,就限流自己,让自己让出系统资源给关联的资源,也就是说在限流自己保护关联资源
  • 链路
    资源通过调用关系,相互之间构成一棵调用树,老抽象了,下面的common和chain/b就是树的关系,这就是一条链路
    在这里插入图片描述

5.1.2 流控效果

  • 直接拒绝
    QPS线程数超过规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时
  • Warm Up
    当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮
  • 匀速排队
    严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求

5.2 测试三种流控模式

5.2.1 直接

默认就是直接

  • 添加规则
    对资源testSentinel/QPSFlowControl添加如下流控规则:如果QPS(每秒查询率)阈值超过1,就直接返回失败
    在这里插入图片描述
    在这里插入图片描述
  • 测试
    快速多次刷新,可以看到,通过6次请求,拒绝14次,规则起作用了
    在这里插入图片描述
    在这里插入图片描述

5.2.2 关联

  • 写了两个请求
@RestController
@Slf4j
@RequestMapping("/testSentinel")
public class FlowControl {

    @GetMapping("related/a")
    public String flowRelatedA(){
        log.info("我是被限流的资源......");
        return "related/a";
    }

    @GetMapping("related/b")
    public String flowRelatedB(){
        log.info("我是被关联资源,不是限流我......");
        return "related/b";
    }
  • 配置/testSentinel/related/a的限流
    如果/testSentinel/related/b的QPS达到1,那么限流/testSentinel/related/a
    -
  • 使用Postman 25秒内访问/testSentinel/related/b 50次,每500ms一次,QPS=2 > 阈值1,满足限流条件
    postman请求之前,可以正常访问/testSentinel/related/a
    在这里插入图片描述
    启动postman请求之后:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    从控制台可以看到/testSentinel/related/b 50次请求全通过,但是/testSentinel/related/a的请求就被拒绝了,测试通过

5.2.3 链路

  • 测试代码,两个请求资源:/testSentinel/chain/a,/testSentinel/chain/b
    flowService.common() 注解为sentinel资源,ab都使用了common方法
@RequestMapping("/testSentinel")
public class FlowController {

    @Autowired
    FlowService flowService;
    
    @GetMapping("chain/a")
    public String chainA(){
        flowService.common();
        return "chain/a";
    }

    @GetMapping("chain/b")
    public String chainB(){
        flowService.common();
        return "chain/b";
    }
@Service
@Slf4j
public class FlowService {

    @SentinelResource
    public void common(){
        log.info("common......");
    }
}

5.3 测试三种流控效果

5.3.1 快速失败

上一节测试的默认都是这种流控效果,返回限流消息或者500错误

5.3.2 Warm Up

初始阈值设定阈值/codeFactor(默认3),经过预热时长阈值升高到设定阈值,让可通过的流量缓慢增长

  • 修改单击阈值为6,流控效果选择 Warm Up
    实际上初始阈值=6/3,为2,经过10秒之后,阈值升高到6
    在这里插入图片描述
  • 测试
    使用postman测试,0.1秒请求一次,总共请求200次,QPS为10 ,持续20http://localhost:8081/testSentinel/QPSFlowControl

在这里插入图片描述
sentinel的实时监控台
21:06:46秒时,通过QPS2,符合 6/3=2
在这里插入图片描述
21:06:58秒开始,通过QPS6,后面稳定6,直到QPS自己降下来,预热时间
58-46=12秒,略大于设置的10秒。总体基本符合限流设置!
在这里插入图片描述

5.3.3 排队等待

这个限流效果只对阈值类型QPS的起作用

  • 设置/testSentinel/QPSFlowContro限流规则
    设置之前清除它其它的容错规则,以免被干扰。设置阈值2,超时时间10秒,
    规则效果:QPS超过阈值的请求,不放弃请求,而是让请求排队等待被执行,服务以一秒2次的速度处理排队的请求,如果某个请求的等待时间超过10秒,才会返回失败
    在这里插入图片描述
  • 测试
    使用postman以一秒10次的速度请求http://localhost:8081/testSentinel/QPSFlowControl 100次,可以看到QPS一直是2100请求全部通过,没有请求被丢弃,符合规则预期!
    在这里插入图片描述
    在这里插入图片描述

6.降级规则限流

在这里插入图片描述

6.1 三种降级策略

6.1.1 RT (Response Time)

6.1.1.1 释义

当1s内持续进入5个请求,对应时刻的平均响应时间(秒级统计,单位毫秒)均超过阈值ms,断路器打开,返回请求失败,知道时间窗口设置的时间结束,关闭降级
在这里插入图片描述

  • RT默认上限是4900 ms
    如需改动,可以通过下面的配置项来设置
-Dcsp.sentinel.statistic.max.rt=xxx
6.1.1.2 测试
  • 测试准备代码
@RestController
@Slf4j
@RequestMapping("/down")
public class DownController {

    @GetMapping("rt/a")
    public String rtA(){
        log.info("rtA....");
        return "rt/a";
    }

}
  • 新增降级规则
    1s内持续进入5个请求,平均响应时间 > 1ms,就返回错误提示,直到4秒之后恢复正常
    在这里插入图片描述
  • 疯狂刷新 http://localhost:8081/down/rt/a,考验手速的时候到了,RT肯定会大于1ms的,于是降级了在这里插入图片描述
    4秒,再次访问,正常了
    在这里插入图片描述

6.1.2 异常比率

6.1.2.1 释义

当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值,资源进入降级状态;接下的时间窗口之后,降级恢复
异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%
在这里插入图片描述

6.1.2.2 测试
  • 写个必抛异常的方法
    要想异常被统计,必须 Tracer.trace(t)
    @GetMapping("rt/b")
    public String rtB() {
        try {
            log.info("rtB....");
            throw new RuntimeException("throw runtime ");
        } catch (Throwable t) {
            Tracer.trace(t);
        }
        return "rt/b";
    }
  • 配置规则
    资源的每秒请求量 >= 5,秒级异常比例 > 0.1,降级,4秒之后恢复
    在这里插入图片描述
  • 测试
    疯狂刷新 http://localhost:8081/down/rt/b,必报异常,所有异常比率 > 0.1
    在这里插入图片描述
    4秒之后在刷新:
    在这里插入图片描述

6.1.3 异常数

6.1.3.1 释义

资源近1分钟的异常数目超过阈值之后会进行降级,统计时间窗口是分钟级别的,所以时间窗口最好大于60s
在这里插入图片描述

6.1.3.2 测试

比较好理解,不测试了

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值