SpringCloudAliBaba篇 之 Sentinel:图解分布式系统的流量防卫兵(上)

简介: SpringCloudAliBaba篇 之 Sentinel:图解分布式系统的流量防卫兵

1、Sentinel是什么

  • Sentinel是阿里巴巴开源的,面向分布式服务架构的高可用防护组件。
  • 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

源码地址:https://github.com/alibaba/Sentinel

官方文档:https://github.com/alibaba/Sentinel/wiki

Sentinel 具有以下特征:

  • 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
  • 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。

阿里云提供了企业级的Sentinel服务,应用高可用服务AHAS

Sentinel和Hystrix对比

Sentinel Hystrix
隔离策略 信号量隔离 线程池隔离/信号量隔离
熔断降级策略 基于响应时间或失败比率 基于失败比率
实时指标实现 滑动窗口 滑动窗口(基于RxJava)
规则配置 支持多种数据源 支持多种数据源
扩展性 多个扩展点 插件的形式
基于注解的支持 支持 支持
限流 基于QPS,支持基于调用关系的限流 有限的支持
流量整形 支持慢启动,匀速器模式 不支持
系统负载保护 支持 不支持
控制台 开箱即用、可配置规则、查看秒级监控、机器发现等 不完善
常见框架的适配 servlet、spring cloud、dubbo、grpc等 servlet、spring cloud netflix

2、sentinel-流控规则初体验(代码层面设置规则)

Sentinel可以简单的分为Sentinel核心库Dashboard。核心库不依赖Dashboard,但是结合Dashboard可以取得最好的效果。

流程规则的定义

重要属性:

Field 说明 默认值
resource 资源名,资源名是限流规则的作用对象
count 限流阈值
grade 限流阈值类型,QPS 模式(1)或并发线程数模式(0) QPS 模式
limitApp 流控针对的调用来源 default,代表不区分调用来源
strategy 调用关系限流策略:直接、链路、关联 根据资源本身(直接)
controlBehavior 流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流 直接拒绝
clusterMode 是否集群限流

通过代码自定义流量控制

1、创建一个springboot项目,并引入sentinel核心库

<!--sentinel核心库-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.4</version>
</dependency>
<!--如果要使用@SentinelResource-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.4</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

编写一个controller

@RestController
@Slf4j
public class HelloController {
    private static final String RESOURCE_NAME = "hello";
    @RequestMapping("/hello")
    public String hello(){
        Entry entry = null;
        try {
            // sentinel针对资源进行限制
            entry = SphU.entry(RESOURCE_NAME);
            // 被保护的业务逻辑
            String str = "hello world";
            log.info("======="+str+"=======");
            return str;
        }catch (BlockException e){
            // 资源访问组织,被限流或被降级,进行响应的处理操作
            log.info("block");
            return "被监控了";
        }catch (Exception ex){
            // 若需要配置降级规则,则需要通过这种方式记录业务异常
            Tracer.traceEntry(ex,entry);
        }finally {
            if(entry != null){
                entry.exit();
            }
        }
        return null;
    }
    /**
     * spring的初始化方法
     *
     **/
    @PostConstruct
    private static void initFlowRules(){
        // 流控规则
        List<FlowRule> rules = new ArrayList<>();
        // 流控
        FlowRule rule = new FlowRule();
        // 为哪个资源设置流控
        rule.setResource(RESOURCE_NAME);
        // 设置流程规则 QPS(每秒的一个访问数)
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值(1秒当中访问一次)
        rule.setCount(1);
        // 加入集合
        rules.add(rule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }
}

结果描述

浏览器进行访问/hello接口,每隔一秒点击一次,正常返回hello world,如果快速点击,返回被监控了

像这样的规则还有熔断降级规则系统保护规则访问控制规则热点规则查询更改规则等等,代码使用方法与上述雷同。

@SentimeResource:注解引入

作用:改善接口中资源定义和被流控降级后的处理方法

1、添加依赖(上面已经引入,我再展示一遍这个依赖)

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.4</version>
</dependency>

2、配置bean

/**
 * 注解支持的配置Bean
 */
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
    return new SentinelResourceAspect();
}

3、在controller层进行代码实现

@RestController
@Slf4j
public class HelloController {
    private static final String RESOURCE_NAME = "hello";
    /**
     * value: 定义的资源
     * blockHandler: 设置流控降级后的处理方法(默认该方法必须声明在同一个类)
     *   如果不想在同一个类中blockHandLerClass但是方法必须是static静态的
     * fallback : 当接口出现了异常,可以调用的方法
     *    如果不想在同一个类中fallbackClass但是方法必须是static静态的
     * 如果blockHandler和fallback同时指定,则blockHandler优先级更高
     * exceptionsToIgnore 排除哪些异常不处理
     **/
    @RequestMapping("/hello")
    @SentinelResource(value = RESOURCE_NAME,blockHandler = "blockHandlerForHello",fallback = "fallbackHandlerHello",exceptionsToIgnore = {})
    public String hello(String id){
        // int i = 1/0;
        return "hello world";
    }
    /**
     * 注意:
     * 1、一定要public
     * 2、返回值一定要和原方法一直,参数也要包含原函数的参数
     */
    public String blockHandlerForHello(String id , BlockException ex){
        ex.printStackTrace();
        return "流控";
    }
    /**
     * 异常会走这个方法
     */
    public String fallbackHandlerHello(String id , Throwable e){
        e.printStackTrace();
        return "异常处理";
    }
    /**
     * spring的初始化方法
     *
     **/
    @PostConstruct
    private static void initFlowRules(){
        // 流控规则
        List<FlowRule> rules = new ArrayList<>();
        // 流控
        FlowRule rule = new FlowRule();
        // 为哪个资源设置流控
        rule.setResource(RESOURCE_NAME);
        // 设置流程规则 QPS(每秒的一个访问数)
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值(1秒当中访问一次)
        rule.setCount(1);
        // 加入集合
        rules.add(rule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }
}

3、sentinel控制台部署

根据需要的版本进行下载下载jar包

windows版本启动

下载完成后,在指定目录下面进行java -jar 你的jar包名称

浏览器直接访问即可,localhost:8080,默认账户名和密码都是sentinel

修改端口号、以及账户名和密码

#需以这种方式启动即可
java -Dserver.port=8810 -Dsentinel.dashboard.auth.username=lili -Dsentinel.dashboard.auth.password=211314 -jar D:\a-mysource\sentinel\sentinel-dashboard-1.8.1.jar

linux版本启动

不做过多描述,命令与windows一样,

注意:如果你想要外界可以访问的话,jar包需要后台启动,可以参考这篇文章当xshell关闭时如何保持一个jar包程序在后台运行

并且打开相应端口防火墙,以及服务器的安全组放行。

效果展示:

本地集成控制台

<!--整合控制台-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.4</version>
</dependency>

编辑我们的启动配置,在对应位置加入(主要是为了根据ip和端口号找到我们的控制台)

-Dcsp.sentinel.dashboard.server=127.0.0.1:8010

启动即可!

注意:刚打开我们的控制台是什么都没有的,随便对一个接口进行访问,再次刷新控制台即可。

4、sentinel整合springcloud alibaba

1、添加依赖

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

2、yml配置

server:
  port: 8005
# 服务名称
spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        #配置sentinel的地址以及端口号
        dashboard: 127.0.0.1:8010

3、编写一个controller

@RestController
@RequestMapping("/order")
public class OrderController {
    @GetMapping("/orderList")
    public String getOrder() {
        return "orderList";
    }    
    @GetMapping("/hello")
    public String getHello() {
        return "hello";
    }
}

启动,先对接口进行一个访问,再进入控制台即可

5、Sentinel控制台各个部分讲解

5.1、实时监控

我们可以对两个请求快速进行访问几次,然后点击实时监控,可以看到请求的一些信息

5.2、簇点链路

  • 用来显示微服务所监控的API

我们经过请求,发现两次请求都被添加进来了。并且可为每个请求进行流控降级热点授权

5.3、流控规则

流量控制,其原理是监控应用流量的QPS或并发线程等指标,当达到指定的阈值对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性

应用场景

  • 应对洪峰流量:秒杀,大促,下单,订单回流处理
  • 消息型场景:削峰填谷,冷热启动
  • 付费系统:根据使用流量付费
  • API Gateway:精准控制API流量
  • 探测应用中运行的慢程序块,进行限制

我们在簇点链路对流控规则进行添加操作,先进行示例QPS方式如下

  • QPS 对应阈值: 表示每秒接受几个请求

解释:该请求每秒最多2个请求,否则就会被流控

测试:浏览器快速刷新,结果如下

结论:成功被流控,这是默认显示,如果想修改默认显示,操作如下

@RestController
@RequestMapping("/order")
public class OrderController {
    @GetMapping("/hello")
    @SentinelResource(value = "hello",blockHandler = "helloHandler")
    public String getHello() {
        return "hello";
    }
    public String helloHandler(BlockException e) {
        return "被流控了";
    }
}

需要对我们刚才自己添加的资源进行流控

再次快速刷新,这个时候就是我们自定义的流控描述了。

再次测试线程数流控

线程数流控是为了保护业务线程池不被慢调用耗尽

  • 线程数对应阈值: 表示每次处理几个线程,其他的线程请求排除在外

实现:添加一个方法

@RequestMapping("/threadHello")
@SentinelResource(value = "threadHello",blockHandler = "helloHandler")
public String threadHello() throws InterruptedException {
    TimeUnit.SECONDS.sleep(5);
    return "hello";
}

打开两个浏览器进行访问(模拟两个线程)

5.3.1、关联流控模式

当两个资源之间具有争抢或者依赖关系的时候,这两个资源便有了关联,比如对数据库同一个字段的读操作和写操作存在争抢,这个时候,我们就可以把读写操作进行关联,当写的操作过于频繁时,读数据的请求就会被限流。

步骤

1、新建两个接口

@GetMapping("/add")
public String add() {
    return "生成订单";
}
@GetMapping("/get")
public String get() {
    return "查询订单";
}

2、生成订单对查询订单限流,当生成订单的次数大于三,则查询订单被限流。

Jmeter工具对/order/add进行每秒四次请求测试,然后浏览器访问/order/get

5.3.2、链路流控模式

下图记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一颗调用树

解释:有两个入口/order/getUser1,/order/getUser2请求都调用了资源User,Sentinel可以选择对其中一个进行资源限制

步骤

1、定义一个接口和对应的实现类

public interface UserService {
    String getUser();
}
@Service
public class UserServiceImpl implements UserService{
    @Override
    @SentinelResource(value = "getUser",blockHandler = "userHandler")
    public String getUser() {
        return "User";
    }
    public String userHandler(BlockException e){
        return "被链路流控了";
    }
}

2、编写controller层

@Autowired
UserService userService;
@GetMapping("/getUser1")
public String getUser1() {
    return userService.getUser();
}
@GetMapping("/getUser2")
public String getUser2() {
    return userService.getUser();
}

3、对getUser2添加链路流控

注意:测试发现功能不生效(高版本不生效)

yml里面加上

spring:
  cloud:
    sentinel:
      web-context-unify: false # 默认将调用链路收敛

再次测试发现

只对order/getUser2进行了流控,而对order/getUser1没有进行流控

5.3.3、预热流控效果

针对激增流量处理

warm up方式,即预热\冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮,通过冷启动让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热时间,避免冷系统被压垮。

冷加载因子:codeFactor默认是3,即请求QPS从threshold/3开始,经预热时长逐渐升至设定的QPS阈值

解释:5s内时间进行预热,直到达到阈值(比如第一秒只能通过三个,第二秒可以通过5个,直到达到阈值)

演示:浏览器快速刷新请求,刚开始会被流控,随着预热,你的刷新速度已经不会被流控了

5.3.4、排队等待流控效果

针对脉冲流量

匀速排队方式会严格控制请求通过的间隔时间,也即是让请求以匀速的速度通过,对应的是漏桶算法

这种方式主要用于处理间隔性突然的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

注意:匀速排队模式暂时不支持QPS>1000的场景

解释:每秒接收5个请求,其他请求进行等待,等待时间为5秒

Jmeter工具对/order/orderList进行每秒10次请求测试,间隔时间为5s,循环5次。

然后观察实施监控

发现:所有的请求都进行了处理,并且还有空闲时间


目录
相关文章
|
5月前
|
监控 算法 Java
高并发架构设计三大利器:缓存、限流和降级问题之配置Sentinel的流量控制规则问题如何解决
高并发架构设计三大利器:缓存、限流和降级问题之配置Sentinel的流量控制规则问题如何解决
|
6月前
|
监控 Java API
深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南
深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南
142 0
深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南
|
6月前
|
SpringCloudAlibaba Java 开发者
SpringCloudAlibaba之Sentinel简单使用
高频率刷新,可以看到hello world、fallback、block handler都会出现。
60 0
|
6月前
|
自然语言处理 监控 开发者
springCloud之Sentinel流量路由、流量控制、流量整形、熔断降级
springCloud之Sentinel流量路由、流量控制、流量整形、熔断降级
131 0
|
7月前
|
SpringCloudAlibaba Rust 监控
SpringCloudAlibaba:5.1Sentinel的基本使用
SpringCloudAlibaba:5.1Sentinel的基本使用
112 0
|
7月前
|
SQL SpringCloudAlibaba Sentinel
【八】SpringCloud Alibaba之整合Sentinel(实现流量控制3)
【八】SpringCloud Alibaba之整合Sentinel(实现流量控制3)
98 2
|
7月前
|
SpringCloudAlibaba Java 测试技术
【七】SpringCloud Alibaba之整合Sentinel(实现流量控制2)
【七】SpringCloud Alibaba之整合Sentinel(实现流量控制2)
96 1
|
4月前
|
Java UED Sentinel
微服务守护神:Spring Cloud Sentinel,让你的系统在流量洪峰中稳如磐石!
【8月更文挑战第29天】Spring Cloud Sentinel结合了阿里巴巴Sentinel的流控、降级、熔断和热点规则等特性,为微服务架构下的应用提供了一套完整的流量控制解决方案。它能够有效应对突发流量,保护服务稳定性,避免雪崩效应,确保系统在高并发下健康运行。通过简单的配置和注解即可实现高效流量控制,适用于高并发场景、依赖服务不稳定及资源保护等多种情况,显著提升系统健壮性和用户体验。
90 1
|
6月前
|
监控 Java Sentinel
使用Sentinel进行服务调用的熔断和限流管理(SpringCloud2023实战)
Sentinel是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
164 3
|
2月前
|
负载均衡 算法 Java
蚂蚁面试:Nacos、Sentinel了解吗?Springcloud 核心底层原理,你知道多少?
40岁老架构师尼恩分享了关于SpringCloud核心组件的底层原理,特别是针对蚂蚁集团面试中常见的面试题进行了详细解析。内容涵盖了Nacos注册中心的AP/CP模式、Distro和Raft分布式协议、Sentinel的高可用组件、负载均衡组件的实现原理等。尼恩强调了系统化学习的重要性,推荐了《尼恩Java面试宝典PDF》等资料,帮助读者更好地准备面试,提高技术实力,最终实现“offer自由”。更多技术资料和指导,可关注公众号【技术自由圈】获取。
蚂蚁面试:Nacos、Sentinel了解吗?Springcloud 核心底层原理,你知道多少?