Spring Cloud Alibaba Sentinel

一、服务雪崩

微服务架构中经常会出现多个服务级联调用的情况,如下图所示:A作为服务提供者,B作为服务消费者,B调用A,C又调用B,D又调用C,如果A出现问题,那么可能导致B调用失败,B出现问题又会导致C调用失败,这样问题不断向上延伸,导致整个系统不可用,也就是服务雪崩了。

导致服务雪崩原因有很多,比如:

  • 流量激增
    • 使用限流机制
  • 缓存问题
    • 使用锁、布隆过滤器、集群解决
  • 硬件故障
    • 异地多活、多机房容灾
  • 程序 bug
    • 测试、代码审查(code review)
  • 线程长时间等待
    • 熔断机制、返回兜底机制

二、 Sentinel 是啥?

Sentinel翻译过来就是哨兵,从字面上理解就是国家如果出现了任何的状况,他会第一时间出现,把危险拦在外面。阿里巴巴的Sentinel组件就是分布式系统的哨兵,它从流量控制、熔断降级、负载保护等多个方面对系统进行保护。

Sentinel的主要特性:

三、 Sentinel VS Hystrix

在SpringCloud Netflix中有一个类似的组件:Hystrix 豪猪,下面我们把哨兵和豪猪进行对比:

可以看到Sentinel的功能更加完善,它的最大特点是有一套Web控制台界面,方便监控和配置各种限流规则,而且Hystrix早已停止更新了,显然Sentinel是它的最佳替代者。

四、安装Sentinel

到Sentinel官网下载jar包,这里使用的版本是1.8.0:Releases · alibaba/Sentinel · GitHub

运行Sentinel的前提是安装了Java环境,Windows系统中打开cmd命令行,切换到jar包所在目录,输入:

java -jar sentinel-dashboard-1.8.0.jar

windows上出现异常可以添加配置

java --add-opens java.base/java.lang=ALL-UNNAMED -jar sentinel-dashboard-1.8.0.jar

就可以看到Sentinel的启动日志

在浏览器输入 http://localhost:8080 就可以看到控制台界面,账号密码默认都是sentinel

登录进去会发现:啥都没有

五、使用Sentinel

下面我们在之前的nacos案例基础上加入Sentinel。1、给provider-service服务添加依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2、application.yml

server:
  port: 8888
spring:
  application:
    name: provider-service
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.7.188:8848
  sentinel:
      transport:
        dashboard: 192.168.7.188:8080 # sentinel 控制台的地址
        port: 8719  # sentinel的端口
management:
  endpoints:
    web:
      exposure:
        include: '*'

3、添加测试的控制器

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "hello sentinel!!";
    }
}

4、启动nacos服务,再启动sentinel控制台,然后启动provider-service服务在nacos里面可以看到该服务

5、在浏览器上输入:http://localhost:8888/hello

然后我们会发现Sentinel的控制台,出来东西了

这就表示我们成功启动了Sentinel,并且用它监控了我们服务的接口调用情况。

六、什么是流控

流控就是流量控制,那么为什么要进行流控呢?

因为大型互联网应用都会有大量的用户流量,当遇到了某些特殊的时间节点,如:双十一秒杀、春节抢票等,大量的流量突然涌入系统,远远超过了服务器的处理能力,服务器可能直接宕机,造成整个系统不可用。

那么对这种问题,我们就需要对流量进行限制,对于超过限制的流量,我们可以采用熔断、降级、排队等待等方式来解决。

七、流控入门

下面我们通过边讲边练的方式,来讲解流控的基本概念。首先我们再执行一下上篇文章的api接口:

然后我们进入Sentinel后台,在簇点链路中,可以看到/hello,在列表右边可以看到添加流控的按钮

八、基本流控规则

点下流控按钮,可以看到

在流控规则窗体里面,可以看到很多选项,那么这些都是些什么东东呢?

我们重点介绍下面三个:

  1. 资源名这个比较好理解,就是api接口的名称了
  2. 阈值类型阈值可以理解为最大值,如水的沸点是100度,水的温度阈值就是100。 那么这个阈值类型就是最大值的不同类型,有两种:
    1. QPS (Query Per Seconds)每秒的请求数,1秒内对资源的请求次数,超过阈值后就启动限流
      1. 线程数 这个就是对资源访问的线程数,超过阈值就启动限流
  3. 单机阈值这个就是根据上面选择的类型,设置的最大值了

九、流控测试

光看文字介绍可能还是不好理解,那么我们来动手操作试试。

先来演示QPS:阈值类型选择QPS,然后单机阈值设置为1,也就是说1秒内请求/hello接口的次数超过1次,就会启动限流,最后点击新增,下面就出现了添加的流控规则:

测试下,浏览器访问下/hello,慢慢点击是没事的,快速点击(1秒点击多次),就会出现下面的文字,意思是被Sentinel进行了限流。

然后我们在编辑下刚才的流控规则,把QPS改为线程数,阈值设置为3,点击保存。

然后我们浏览器测试刚才的接口,可以看到不管点多快,接口都可以正常访问,没有出现限流。

那么怎么才能按线程数实现限流呢?我们可以使用JMeter进行测试,JMeter的基本使用这里就不介绍了,大家可以百度下。

1) 添加线程组

2) 设置线程数为5和永远循环,意思就是每次都会启动5个线程来访问上面的接口

3) 添加取样器

配置接口访问的选项

4) 可以添加个监听器,看访问结果

5) 最后点击上面的启动测试按钮

结果是:出现了限流

十 、流控模式

打开流控的高级选项,可以看到流控模式和流控效果两个选项。

直接

默认的流控模式是直接,流控效果是快速失败。如果看过上篇文章就比较好理解,直接就是直接访问上面的资源,快速失败就是效果是访问失败直接出现限流的文字。

关联

我们再看看关联是什么,微服务的系统资源一般都有关联关系,比如:订单接口会调用支付接口,如果支付接口出现流量激增的情况,会导致调用订单接口出现问题,这时我们除了直接对支付接口限流外,也可以对订单接口限流。

为验证效果,我们编写控制器

@RestController
public class OrderController {

    @GetMapping("/order")
    public String order(){
        return "这是订单接口!";
    }

    @GetMapping("/payment")
    public String payment(){
        return "这是支付接口!";
    }
}

先访问一下/order接口,然后给它添加流控规则,流控模式选择关联,关联资源设置为/payment,也就是:payment接口每秒访问超过1次后,将对order接口进行限流。

测试还是使用JMeter,配置线程组、HTTP请求。

这是http配置的是访问payment接口

启动测试前,order接口访问是正常的。

启动测试后,order接口被限流了。

总结一下,关联就是:关联资源超过了阈值,限流当前的资源。

链路

链路是资源的调用可能出现上下级的层次结构,如下图:

A是根节点,以A为入口,可以访问B和C,B和C又可以访问D和E,那么我们如果对A进行限流,就可以对A下面的所有资源进行限流了。

做下测试:查看簇点链路,选择树状视图,就可以看到上下级的关系了。

我们看到上层的资源是/order,下层资源也是/order,给下面的/order添加流控

测试/order,会出现限流

十一、流控效果

上面我们了解了流控的几种模式,下面我们在来了解下流控效果:

快速失败

快速失败是默认效果,既当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。

Warm Up

即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。比如:在春节抢热点地区火车票的时候,如果直接把流量放进来,可能会一下直接把12306的服务器打死,那么我们可以设定一个预热时间,给服务器一个缓冲期,慢慢的把流量放进来,直到达到最大的阈值。

修改一下前面的流控规则,这里阈值是10,预热时间是5秒,前面讲过流量是逐步加到阈值上限的,那么就有一个初始的阈值: 初始阈值 = 阈值上限 / coldFactor, coldFactor 是冷加载因子,默认为3,则初始阈值为 10 / 3 = 3 下面配置的效果就是:一开始限流的阈值是3,然后5秒后上升到10.

测试时,快速点击(1秒3次以上),就会出现限流

等5秒后,再快速点击,都没有限流,因为阈值上升到10了

排队等待

排队等待方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。也比较好理解,就是不管流量再多,进来访问资源时都必须排队,一个个的访问。这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

为方便查看效果,给接口加上日志

@Slf4j
@RestController
public class OrderController {

    @GetMapping("/order")
    public String order(){
        log.info("Thread:{},time:{}",Thread.currentThread().getName(),System.currentTimeMillis());
        return "这是订单接口!";
    }

    @GetMapping("/payment")
    public String payment(){
        return "这是支付接口!";
    }
}

修改下流控

快速访问/order,发现日志输出的时间间隔都是控制在1秒,也就是排队等待设置的超时时间

十二、@SentinelResource

Sentinel提供了@SentinelResource来处理限流、熔断降级注解的配置基于AOP实现,需要添加Aspect配置

@Configuration
public class SentinelAspectConfiguration {

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }	
}

@SentinelResource的源码

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
    String value() default "";

    EntryType entryType() default EntryType.OUT;

    int resourceType() default 0;

    String blockHandler() default "";

    Class<?>[] blockHandlerClass() default {};

    String fallback() default "";

    String defaultFallback() default "";

    Class<?>[] fallbackClass() default {};

    Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};

    Class<? extends Throwable>[] exceptionsToIgnore() default {};
}

@SentinelResource的属性

  • value 资源名称
  • entryType entry类型,有IN、OUT两种
  • blockHandler 限流处理方法
  • blockHandlerClass 限流处理类
  • fallback 熔断降级处理方法
  • fallbackClass 熔断降级处理类
  • exceptionsToTrace 异常跟踪列表

十二、限流处理

前面出现限流情况后,都会出现一样的错误信息,那么我们是否能定义一个自己的限流处理方法呢?在

@Slf4j
@RestController
@RequestMapping("provider")
public class GoodsController {

    @GetMapping("goods")
    @SentinelResource(value = "goods",blockHandler = "findGoodsExceptionHandler")
    public String findGoods(){
        log.info("正常返回商品");
        return "正常返回商品";
    }

    public String findGoodsExceptionHandler(BlockException ex){
        log.error("出现限流",ex);
        return "出现限流";
    }

blockHandler属性指定限流处理的方法名,默认情况下该方法必须定义在当前类中,而且参数和返回值和原方法一致,可以多定义一个BlockException参数代表限流异常。

如果不希望处理方法和原方法耦合在一起,可以单独定义处理类,处理方法必须是静态的。

@Slf4j
public class MyBlockHandler {

    public static String findGoodsExceptionHandler(BlockException ex){
        log.error("出现限流",ex);
        return "出现限流";
    }
}

然后@SentinelResource加上属性

blockHandlerClass = MyBlockHandler.class

配置限流规则

出现限流后,调用的是自定义方法

十三、处理降级

通过fallback属性指定降级方法,降级方法必须在同一个类中,返回值和参数和原方法一致

@Slf4j
@RestController
@RequestMapping("provider")
public class GoodsController {

    @GetMapping("goods")
    @SentinelResource(value = "goods",fallback = "findGoodsFallback")
    public String findGoods(){
        if(new Random().nextInt(2) == 0){
            throw new RuntimeException("Error");
        }
        log.info("正常返回商品");
        return "正常返回商品";
    }


    public String findGoodsFallback(){
        log.info("出现异常熔断");
        return "出现异常熔断";
    }
}

十四、添加一个降级规则,选择异常数,异常数、熔断时长、请求数都设置为1

原方法有1/2的机会抛出异常,抛出异常后,调用了降级方法

十五、分布式系统相关原理

CAP 原理

什么是 CAP 原理?

分布式系统都符合的一个原理,包含:

C 一致性(同样的数据在多个节点上保持一致)

A 可用性(节点能随时提供服务)

P 分区容错性(系统分为多个节点,其中节点出现故障,其余的节点可以继续提供)

三个特性,只能同时存在两个,主要是因为网络的不可确定性。

分布式系统都需要有分区容错性,否则就是单体应用,数据进行同步的时间内,数据可能出现不一致,为了保证数据一致,可能需要让服务下线,又会导致服务不可用。

如何选择 AP、CP ?

对一致性要求非常严格的系统 CP,银行、经融...

对可用性要求高 AP,社交、短视频、电商...

BASE 原理

CPA 理论的衍生

Basic Avialbility 基本可用,大多数服务能提供服务,绝大多数功能正常使用

Soft state 软状态

数据在完成同步前,允许存在中间状态

E 最终一致性

数据通过一系列手段,最终达到一致

十六、总结

1、熔断器是什么?

是一种保证服务可用性的机制,如果服务出现异常或长时间等待,可以进行熔断然后降级处理,保证大多数服务正常运行

Sentinel可以实现限流和熔断降级

2、Sentinel提供了很多流控规则

包含: 资源名称、分组、流控阈值,流控类型(QPS、线程数),流控模式,流控效果

3、Sentinel通过@SentinelResource注解可以自定义限流和熔断降级的处理方法
 


 

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring CloudSpring Cloud Alibaba都是基于Spring Framework的开源框架,用于构建分布式系统和微服务架构。它们都提供了一系列的组件和工具来简化微服务开发和管理。 Spring Cloud是一个由Pivotal团队维护的项目,它集成了Netflix开源的一些组件,如Eureka作为注册中心、Ribbon作为负载均衡器、Feign作为服务调用工具等。同时,Spring Cloud还提供了其他功能,如Config Server用于动态管理配置、Gateway用于构建API网关等。 而Spring Cloud Alibaba则是阿里巴巴开源的项目,它在Spring Cloud的基础上进行了扩展和定制,增加了一些阿里巴巴自己的组件和工具。比如,它使用Nacos作为注册中心和配置中心,使用Sentinel作为熔断降级工具。 总的来说,Spring CloudSpring Cloud Alibaba都是用于构建微服务架构的框架,它们的区别在于Spring Cloud集成了Netflix组件,而Spring Cloud Alibaba集成了阿里巴巴的一些组件。根据具体的需求和技术栈选择使用哪个框架可以更好地满足开发和管理微服务的需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Spring Cloud AlibabaSpring Cloud的区别](https://blog.csdn.net/weixin_43888891/article/details/126653270)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值