Spring Cloud Alibaba Sentinel 使用

初识Sentinel

Sentinel是阿里巴巴开源的一款微服务流量控制组件。官网地址: home | Sentinel

需要了解的概念

簇点链路

在学习 Sentinel 的使用之前,我们有必要首先了解一下簇点链路。当请求进入微服务时,首先会访Controller、Service、Mapper,这样的一个调用链就叫做簇点链路。链路中被监控的每个接口就是一个资源。默认情况下 Sentinel 会监控 Spring MVC 的每一个端点(Endpoint),因此 SpringMVC 的每一个端点(Endpoint)就是调用链路中的一个资源。

簇点链路中的资源可以认为就是一个Controller中的接口路径。

流控、熔断等都是针对簇点链路中的资源来设置的。

下载

下载sentinel-dashboard的jar包:https://github.com/alibaba/Sentinel/releases/tag/1.8.6

上传到服务器

部署sentinel-dashboard

前置:服务器需要安装好JDK

启动命令如下

复制代码
java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=192.168.1.5:8090 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=sentinel  -jar sentinel-dashboard-1.8.6.jar

启动参数解释

-Dserver.port=8090 // 指定启动端口,默认8080建议更换端口号

-Dcsp.sentinel.dashboard.server=localhost:8080 // Sentinel Dashboard 地址,地址格式:ip:port,客户端会自动向该地址发送心跳包,必须进行配置

-Dproject.name=sentinel-dashboard // 指定sentinel控制台服务的名字

-Dsentinel.dashboard.auth.username=sentinel // 指定sentinel登录名,可选,默认sentinel

-Dsentinel.dashboard.auth.password=sentinel // 指定sentinel登录密码,可选,默认sentinel

访问http://localhost:8090,如下图所示,默认的账户和密码都是sentinel

登录成功后,便可查看控制台内部信息,默认会监控sentinel-dashboard服务本身

Sentinel 的简单使用示例

QPS限流

场景

我们需要对 /getProductById这个路径进行QPS限流,要求它的 QPS 每秒不能超过 1,即每秒访问不能超过一次,设置步骤如下

准备前置条件

  1. 启动sentinel控制台,如果不是同一台机器注意打开防火墙端口号

  2. 准备一个SpringBoot项目中,服务名为:sky-product,开发一个API接口,url为:/getProductById

    @GetMapping("/getProductById")
    public String getProductById(Integer id) {
    log.info("入参:{}",id);
    if(id==null){
    log.error("getProductById 入参为 null");
    id=1;
    }
    return productService.getProductById(id);
    }

  3. 引入sentinel依赖

    com.alibaba.cloud spring-cloud-starter-alibaba-sentinel
  4. 修改yml配置文件

    spring:
    cloud:
    sentinel:
    transport:
    dashboard: localhost:8090 # 配置控制台ip和端口

  5. 现在启动这个服务

  6. 先访问/getProductById接口

  1. 访问后刷新控制台,sentinel默认为懒加载,看不到可以多刷新几次

限流规则配置

  1. 添加限流规则,点击流控按钮
  1. 类型选择QPS,单机阈值填1,点击新增按钮
  1. 新增之后,可以在流控规则中查看这条新增的规则
  1. 测试,快速访问这个接口,会发现出现限流提示,状态码为429

线程隔离限流

场景

sky-product服务中的 /getProductById接口被sky-system服务中getUserBuy接口调用,

在高并发场景下,如果getProductById接口出现响应缓慢的情况,可能会出现拖慢sky-system服务,将sky-system服务资源耗尽,即出现服务雪崩的情况。

解决方案如下

这时可以对getUserBuy接口进行线程池隔离限流,比如设置线程数为5,这样sky-system服务最多只会有5个线程去访问getProductById接口,不会出现资源耗尽的情况。

前置条件准备

  1. 首先按照QPS限流前置条件准备

  2. 创建sky-system服务

  3. 增加getUserBuy接口

    @GetMapping("/getUserBuy")
    public String getUserBuy(String userId) {
    log.info("入参:{}",userId);
    return userService.getUserBuy(userId);
    }

  4. 增加feign client

    @FeignClient(contextId = "remoteProductService", name = "sky-product")
    public interface RemoteProductService {

    复制代码
     @GetMapping("/product/getProductById")
     String getProductById(@RequestParam("id") Integer id);

    }

  5. getUserBuy接口service代码,远程调用sky-product中的getProductById接口

    @Override
    public String getUserBuy(String userId) {
    //获取一个随机的整数 1-100
    int intnum = new Random().nextInt(100);
    log.info("开始执行方法");
    return remoteProductService.getProductById(intnum);
    }

限流规则配置

  1. 添加限流规则,点击流控按钮

  2. 类型选择并发线程数,单机阈值填5,点击新增按钮

  1. 在getProductById接口中增加Thread.sleep(500),方便进行测试
  2. 使用jemter测试,平均每秒100个请求
  1. 查看sentinel实时监控,可以看到平均QPS为10,结果符合预期

对OpenFeign调用进行限流

在一般情况下我们是针对远程调用进行限流,在Spring Cloud项目中主要是针对OpenFeign进行限流

配置簇点链路展示feign接口

在sky-system服务yml配置文件增加如下配置

复制代码
feign:
  sentinel:
    enabled: true

访问getuserBy接口,刷新Sentinel控制台,可以看到展示了OpenFeign接口,我们可以给这个接口配置限流规则

给OpenFeign增加Fallback配置

这样可以在发生异常或流控时做一些处理,比如返回默认值或者有好的提示等。

  1. 增加一个类,实现FallbackFactory,并声明为一个bean

    @Component
    @Slf4j
    public class RemoteProductFallback implements FallbackFactory {

    复制代码
     @Override
     public RemoteProductService create(Throwable cause) {
         log.info("异常:{}",cause.getMessage());
         return new RemoteProductService() {
             @Override
             public String getProductById(Integer id) {
                 return "出现限流了,我是默认返回值";
             }
         };
     }

    }

  2. 修改FeignClient,增加fallbackFactory属性

    @FeignClient(contextId = "remoteProductService", name = "sky-product",fallbackFactory = RemoteProductFallback.class)
    public interface RemoteProductService {

    复制代码
     @GetMapping("/product/getProductById")
     String getProductById(@RequestParam("id") Integer id);

    }

  3. 重启后进行测试

  4. 先访问getUserBuy接口,刷新控制台设置流控规则,这里阈值设置为1方便测试

  1. 快速请求接口,返回了fallback提示

熔断

熔断是解决雪崩问题的重要手段。思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。

我们给openfeign接口配置一下熔断策略

  1. 访问getUserBuy接口,刷新控制台,点击熔断按钮
  1. 修改getProductById方法,接口延时为100-200之间

    @GetMapping("/getProductById")
    public String getProductById(Integer id) {
    Random random = new Random();
    int min = 100; // 范围最小值
    int max = 200; // 范围最大值
    int randomNumber = random.nextInt(max - min + 1) + min;
    try {
    Thread.sleep(randomNumber);
    } catch (InterruptedException e) {
    throw new RuntimeException(e);
    }
    log.info("入参:{}",id);
    if(id==null){
    log.error("getProductById 入参为 null");
    id=1;
    }
    return productService.getProductById(id);
    }

  2. 熔断配置如下,表示在1秒内请求数超过5,并且有70%请求时间超过110ms,则会熔断10s

  1. 配置流控规则,给openfeign接口限制了最大10个线程
  1. 使用jemeter进行测试,每秒钟10个请求
  1. 在没有配置熔断,只配置流控的情况下所有的请求都是正常的。我们看下配置了熔断的情况发现出现了熔断的情况。

生产环境使用

在前面测试时已经发现,服务重启后配置的规则就消失了,这在生产上是不可以的。

官方推荐生产模式使用Push模式,使用Nacos配置中心来管理sentinel规则在生产环境中使用 Sentinel · alibaba/Sentinel Wiki · GitHub

生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel,而不是经 Sentinel 数据源推送至配置中心。这样的流程就非常清晰了:

微服务中增加基于Nacos的写数据源(WritableDataSource),当 Sentinel Dashboard 配置发生变更,则利用 nacos 配置变更通知微服务更新本地缓存。

下面我们来结合Nacos使用Sentinel

POM文件引入下面的依赖

复制代码
getUserBuy
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

yml配置文件修改

我们使用nacos配置文件来对服务进行流控、熔断等操作,所以就需要有以下几个必须的参数:

data-id:需要告诉sentinel读取配置中心中的哪个配置文件。

rule-type:告诉sentinel配置文件配置的控制规则,flow:流控、degrade:熔断、param-flow热点参数,想看有哪些规则参数可以查看com.alibaba.cloud.sentinel.datasource包下的枚举类:RuleType。

现在在yml配置文件增加下面的配置

复制代码
spring:
  application:
    name: sky-system
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
      config:
        # 配置中心地址
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        # 配置中心的文件格式
        file-extension: yml
    sentinel:
      datasource:
        flow-rules: #流控规则
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-flow-rules
            data-type: json
            rule-type: flow
        degrade-rules: #熔断规则
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-degrade-rules
            data-type: json
            rule-type: degrade
        param-flow-rules:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-param-flow-rules
            data-type: json
            rule-type: param-flow
        authority-rules:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-authority-rules
            data-type: json
            rule-type: authority
        system-rules:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-system-rules
            data-type: json
            rule-type: system

Nacos上增加规则文件

因为上面配置文件中指定了Nacos配置文件的名称格式: dataId: ${spring.application.name}-xxx.json,所以

配置限流规则需要先创建 sky-system-flow-rules.json

配置熔断规则需要先创建sky-system-degrade-rules.json配置集,其他服务类似

存在一个问题:nacos中的配置文件对于sentinel来讲是单项数据读入,sentinel能监听到nacos中配置的变化,但是我们在sentinel中修改了配置,nacos是不会监听到并进行修改。所以不能通过sentinel控制台来配置,只能通过nacos来配置规则。

配置限流规则

在nacos上编辑sky-system-flow-rules配置,填入下面的内容

复制代码
[{
    "resource":"/getUserBuy",
    "grade":0, 
    "count":10, 
    "strategy":0, 
    "controlBehavior":0,
    "clusterMode":false
}
]

效果和下图一样

说明

{ "resource": "/test", // 资源名 "limitApp": "default", // // 针对来源,若为 default 则不区分调用来源 "grade": 1, // 限流阈值类型(1:QPS; 0:并发线程数) "count": 1, // 阈值 "clusterMode": false, // 是否是集群模式 "controlBehavior": 0, // 流控效果 (0:快速失败; 1:Warm Up(预热模式); 2:排队等待) "strategy": 0, // 流控模式(0:直接; 1:关联; 2:链路) "warmUpPeriodSec": 10, // 预热时间(秒,预热模式需要此参数) "maxQueueingTimeMs": 500, // 超时时间(排队等待模式需要此参数) "refResource": "rrr" // 关联资源、入口资源(关联、链路模式) }

刷新sentinel控制台,可以看到配置已经生效

配置熔断规则

在nacos上编辑sky-system-degrade-rules配置,填入下面的内容

复制代码
[
    {
        "resource": "GET:http://sky-product/product/getProductById",
        "grade": 0, 
        "count": 110, 
        "slowRatioThreshold": 0.7,
        "minRequestAmount":  10, 
        "timeWindow": 10, 
        "statIntervalMs": 1000 
    }
]	

效果和下图一致

说明

{ "resource": "/ceshi", "grade": 0, // 熔断策略,支持慢调用比例(0),异常比例(1),异常数(2)策略 "count": 1000, // 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用,单位ms);异常比例/异常数模式下为对应的阈值 "slowRatioThreshold": 0.1,// 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) "minRequestAmount": 10, //熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断 "timeWindow": 10, // 熔断时长,单位为 s "statIntervalMs": 1000 // 统计时长(单位为 ms),如 60\*1000 代表分钟级 }

刷新sentinel控制台,可以看到配置已经生效

相关推荐
code_slave(码畜)18 分钟前
微服务架构落地:分库分表实战(下) —— 分布式主键、跨分片查询与分页聚合防坑
数据库·spring boot·分布式·spring cloud·微服务·架构·分库分表
萧瑟余晖1 小时前
Spring Cloud综合实战与架构选型详解
spring·spring cloud·架构
萧瑟余晖3 小时前
Spring Cloud Alibaba生态整合详解
spring·spring cloud·面试
每天一道题4 小时前
Kafka 为什么会重复消费?从 Producer ACK、Offset 到消息可靠性
后端·微服务
萧瑟余晖1 天前
Spring Cloud分布式事务与链路追踪详解
分布式·spring·spring cloud
ん贤1 天前
温习微服务基础知识
微服务·云原生·架构
zzu123zsw1 天前
业务拆分后的治理深水区:解构企业级微服务六大核心设计模式与高可用落真实践
微服务·设计模式·架构·高可用·微服务架构设计
code_slave(码畜)2 天前
微服务架构落地:读写分离架构 —— 主从延迟引发的“刚开单查不到”灾难与破局
spring boot·分布式·spring cloud·微服务·云原生·架构·读写分离
2501_933923252 天前
SpringCloud组件:Nacos服务注册快速入门
后端·spring·spring cloud·nacos