• 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
    1. @GetMapping("/getProductById")
    2. public String getProductById(Integer id) {
    3. log.info("入参:{}",id);
    4. if(id==null){
    5. log.error("getProductById 入参为 null");
    6. id=1;
    7. }
    8. return productService.getProductById(id);
    9. }
    1. 引入sentinel依赖
    1. <dependency>
    2. <groupId>com.alibaba.cloud</groupId>
    3. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    4. </dependency>
    1. 修改yml配置文件
    1. spring:
    2. cloud:
    3. sentinel:
    4. transport:
    5. dashboard: localhost:8090 # 配置控制台ip和端口
    1. 现在启动这个服务
    2. 先访问/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接口
    1. @GetMapping("/getUserBuy")
    2. public String getUserBuy(String userId) {
    3. log.info("入参:{}",userId);
    4. return userService.getUserBuy(userId);
    5. }
    1. 增加feign client
    1. @FeignClient(contextId = "remoteProductService", name = "sky-product")
    2. public interface RemoteProductService {
    3. @GetMapping("/product/getProductById")
    4. String getProductById(@RequestParam("id") Integer id);
    5. }
    1. getUserBuy接口service代码,远程调用sky-product中的getProductById接口
    1. @Override
    2. public String getUserBuy(String userId) {
    3. //获取一个随机的整数 1-100
    4. int intnum = new Random().nextInt(100);
    5. log.info("开始执行方法");
    6. return remoteProductService.getProductById(intnum);
    7. }

    限流规则配置

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

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

    1. 在getProductById接口中增加Thread.sleep(500),方便进行测试
    2. 使用jemter测试,平均每秒100个请求

    1. 查看sentinel实时监控,可以看到平均QPS为10,结果符合预期

    对OpenFeign调用进行限流

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

    配置簇点链路展示feign接口

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

    1. feign:
    2. sentinel:
    3. enabled: true

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

    给OpenFeign增加Fallback配置

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

    1. 增加一个类,实现FallbackFactory,并声明为一个bean
    1. @Component
    2. @Slf4j
    3. public class RemoteProductFallback implements FallbackFactory<RemoteProductService> {
    4. @Override
    5. public RemoteProductService create(Throwable cause) {
    6. log.info("异常:{}",cause.getMessage());
    7. return new RemoteProductService() {
    8. @Override
    9. public String getProductById(Integer id) {
    10. return "出现限流了,我是默认返回值";
    11. }
    12. };
    13. }
    14. }
    1. 修改FeignClient,增加fallbackFactory属性
    1. @FeignClient(contextId = "remoteProductService", name = "sky-product",fallbackFactory = RemoteProductFallback.class)
    2. public interface RemoteProductService {
    3. @GetMapping("/product/getProductById")
    4. String getProductById(@RequestParam("id") Integer id);
    5. }
    1. 重启后进行测试
    2. 先访问getUserBuy接口,刷新控制台设置流控规则,这里阈值设置为1方便测试

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

    熔断

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

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

    1. 访问getUserBuy接口,刷新控制台,点击熔断按钮

    1. 修改getProductById方法,接口延时为100-200之间
    1. @GetMapping("/getProductById")
    2. public String getProductById(Integer id) {
    3. Random random = new Random();
    4. int min = 100; // 范围最小值
    5. int max = 200; // 范围最大值
    6. int randomNumber = random.nextInt(max - min + 1) + min;
    7. try {
    8. Thread.sleep(randomNumber);
    9. } catch (InterruptedException e) {
    10. throw new RuntimeException(e);
    11. }
    12. log.info("入参:{}",id);
    13. if(id==null){
    14. log.error("getProductById 入参为 null");
    15. id=1;
    16. }
    17. return productService.getProductById(id);
    18. }
    1. 熔断配置如下,表示在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文件引入下面的依赖

    1. getUserBuy
    2. <dependency>
    3. <groupId>com.alibaba.cloud</groupId>
    4. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    5. </dependency>
    6. <dependency>
    7. <groupId>com.alibaba.csp</groupId>
    8. <artifactId>sentinel-datasource-nacos</artifactId>
    9. </dependency>

    yml配置文件修改

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

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

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

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

    1. spring:
    2. application:
    3. name: sky-system
    4. cloud:
    5. nacos:
    6. discovery:
    7. # 服务注册地址
    8. server-addr: 127.0.0.1:8848
    9. config:
    10. # 配置中心地址
    11. server-addr: ${spring.cloud.nacos.discovery.server-addr}
    12. # 配置中心的文件格式
    13. file-extension: yml
    14. sentinel:
    15. datasource:
    16. flow-rules: #流控规则
    17. nacos:
    18. server-addr: localhost:8848
    19. dataId: ${spring.application.name}-flow-rules
    20. data-type: json
    21. rule-type: flow
    22. degrade-rules: #熔断规则
    23. nacos:
    24. server-addr: localhost:8848
    25. dataId: ${spring.application.name}-degrade-rules
    26. data-type: json
    27. rule-type: degrade
    28. param-flow-rules:
    29. nacos:
    30. server-addr: localhost:8848
    31. dataId: ${spring.application.name}-param-flow-rules
    32. data-type: json
    33. rule-type: param-flow
    34. authority-rules:
    35. nacos:
    36. server-addr: localhost:8848
    37. dataId: ${spring.application.name}-authority-rules
    38. data-type: json
    39. rule-type: authority
    40. system-rules:
    41. nacos:
    42. server-addr: localhost:8848
    43. dataId: ${spring.application.name}-system-rules
    44. data-type: json
    45. 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配置,填入下面的内容

    1. [{
    2. "resource":"/getUserBuy",
    3. "grade":0,
    4. "count":10,
    5. "strategy":0,
    6. "controlBehavior":0,
    7. "clusterMode":false
    8. }
    9. ]

    效果和下图一样

    说明

    [

    {

    "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配置,填入下面的内容

    1. [
    2. {
    3. "resource": "GET:http://sky-product/product/getProductById",
    4. "grade": 0,
    5. "count": 110,
    6. "slowRatioThreshold": 0.7,
    7. "minRequestAmount": 10,
    8. "timeWindow": 10,
    9. "statIntervalMs": 1000
    10. }
    11. ]

    效果和下图一致

    说明

    [

    {

    "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控制台,可以看到配置已经生效

  • 相关阅读:
    节日网页HTML代码 学生网页课程设计期末作业下载 清明节大学生网页设计制作成品下载 DW节日网页作业代码下载
    基于PHP+MySQL医药信息查询系统的设计与开发
    面试那些题(1)
    JDBC —— 数据库连接
    Linux--忘记root密码解决办法
    2.20数据结构与算法学习日记(二叉树第一部分)
    算法结构之选择排序
    Linux Shell bash脚本中的 $! $$ $- $0 $1~$n ${n} $# $@ $* $?
    万字详解-MindArmour 小白教程!
    uniapp 在 onLoad 事件中 this.$refs 娶不到的问题
  • 原文地址:https://blog.csdn.net/moxiong3212/article/details/138185123