微服务实战(四) Sentinel 服务的限流 熔断 降级

微服务实战(四) Sentinel 服务的限流 熔断 降级

  • 官方文档:https://sentinelguard.io/zh-cn

概述

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。

功能

  • 多样化的流量控制

  • 熔断降级

  • 系统负载保护

  • 实时监控和控制台

组成部分

Sentinel 的使用可以分为两个部分:

  • 核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持(见 主流框架适配)。

  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。

Sentinel 与 Hystrix

SentinelHystrix都能实现服务的限流、熔断、降级,上篇微服务实战(三) OpenFegin 声明式服务调用也简单介绍了Hystrix的熔断和降级。不敢说那个服务更好用,但就学习而言,Sentinel 文档要详细的多。

Hystrix在2018年也官宣进入维护模式,称Hystrix(版本1.5.18)足够稳定,可以满足Netflix对我们现有应用程序的需求,并将resilience4j这样的开放和活动项目用于新的内部项目。虽然不影响现有的项目,但相信会有越来越多的人倾向于选择Sentinelresilience4j等。

Sentinel官方文档也简单做了同类组件功能对比:

Sentinel Hystrix resilience4j
隔离策略 信号量隔离(并发控制) 线程池隔离/信号量隔离 信号量隔离
熔断降级策略 基于慢调用比例、异常比例、异常数 基于异常比例 基于异常比例、响应时间
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于 RxJava) Ring Bit Buffer
动态规则配置 支持近十种动态数据源 支持多种数据源 有限支持
扩展性 多个扩展点 插件的形式 接口的形式
基于注解的支持 支持 支持 支持
单机限流 基于 QPS,支持基于调用关系的限流 有限的支持 Rate Limiter
集群流控 支持 不支持 不支持
流量整形 支持预热模式与匀速排队控制效果 不支持 简单的 Rate Limiter 模式
系统自适应保护 支持 不支持 不支持
热点识别/防护 支持 不支持 不支持
多语言支持 Java/Go/C++ Java Java
Service Mesh 支持 支持 Envoy/Istio 不支持 不支持
控制台 提供开箱即用的控制台,可配置规则、实时监控、机器发现等 简单的监控查看 不提供控制台,可对接其它监控系统

Sentinel 控制台

Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。 基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。

下载地址:https://github.com/alibaba/Sentinel/releases

启动

#-Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080
#-Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
#-Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;
#-Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

访问http://ip:8080

微服务实战(四) Sentinel 服务的限流 熔断 降级_第1张图片

客户端接入

  • Nacos+OpenFeign+Sentinel(Sentinel Spring Cloud)

引入依赖


<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>


<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>


<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

添加配置

  • Feign取消feign.hystrix.enabled配置或设置为false
  • Feign添加feign.sentinel.enabled配置
spring:
  application:
    name: sunnyws-service-example2
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 172.16.220.10:8848
        namespace: e90d261b-9c05-4bcb-b99f-b419d952737a
      config:
        server-addr: 172.16.220.10:8848
        file-extension: yml
        namespace: e90d261b-9c05-4bcb-b99f-b419d952737a
    sentinel:
      transport:
        #控制台地址
        dashboard: 172.16.220.10:8080
        port: 8917
      eager: true

feign:
  sentinel:
    enabled: true

management:
  # 端点检查(健康检查)
  endpoints:
    web:
      exposure:
        include: "*"

Sentinel 控制台添加配置

流控规则
阈值类型
  • QPS:每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
  • 线程数:访问该资源的线程数。
流控模式
  • 直接:当达到阈值就进行限流。
  • 关联:当关联的资源达到阈值,就限流自己。
    • 适用场景:查询和修改同一表的数据,如果是高并发的应用,查询接口的流量过大,就会影响修改接口的性能,反之同理,这就可以根据业务需求,去衡量希望优先读还是优先写。
    • 关联其实是一种保护关联资源的设计。
  • 链路:只记录指定链路上的流量,即指定资源从入口资源进来的流量如果达到阈值就限流。
    • 链路其实是一种细粒度的针对来源,而编辑流控规则中的针对来源输入框是微服务级别的,可以指定指定微服务过来的流量达到阈值就限流。
    • 而链路是api级别的,指定的是api的调用流量达到阈值就限流。
流控效果
  • 快速失败:直接失败,抛异常

  • Warm Up(预热):根据codeFactor(冷加载因子,默认值为3),从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。
    即如果阈值为100,冷加载因子为3,预热时长为10秒,那么就会用100 / 3作为最初的阈值,经过10秒之后才会将阈值达到100,进而进行限流,意思就是让允许通过的流量缓慢增加,在达到一定的时间之后才达到阈值这样会更好的保护微服务

  • 排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置成QPS,否则无效。此种模式可适用于应对突发流量的场景

微服务实战(四) Sentinel 服务的限流 熔断 降级_第2张图片

熔断策略
  • Sentinel 1.8后对熔断降级做了大的调整,可以定义任意时长的熔断时间,引入了半开启恢复支持。
  • OpenFeign+Sentinel 熔断后降级 是将fallback交给feign处理
  • Sentinel 默认统计的RT上限是4900ms,超出此阈值的都会算作4900ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx来配置
  • 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
  • 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
  • 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

微服务实战(四) Sentinel 服务的限流 熔断 降级_第3张图片

Sentinel持久化

  • Sentinel 默认将规则保存在内存中,重启即消失。

  • 生产环境的 Sentinel Dashboard 规则需要集中管理和持久化。

官方文档中提到了三种推送模式来管理规则的推送。

推送模式 说明 优点 缺点
原始模式 API 将规则推送至客户端并直接更新到内存中,扩展写数据源(WritableDataSource 简单,无任何依赖 不保证一致性;规则保存在内存中,重启即消失。严重不建议用于生产环境
Pull 模式 扩展写数据源(WritableDataSource), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等 简单,无任何依赖;规则持久化 不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。
Push 模式 扩展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源。 规则持久化;一致性;快速 引入第三方依赖

官方建议采用Push模式的数据源,并提供了 ZooKeeper, Apollo, Nacos 等的动态数据源实现,流程图如下:

微服务实战(四) Sentinel 服务的限流 熔断 降级_第4张图片

使用Nacos存储Sentinel的限流规则

  • 采用官方建议的Push模式,配置持久化保存在Nacos,客户端监听Nacos.
  • 这里示例为OpenFeign+Nacos+Sentinel,sentinel规则类型为flow
  • 当前版本的Sentinel Dashboard不具备同步修改Nacos配置的能力,需要手动修改代码。
不修改Sentinel Dashboard代码
  • 不需要修改Sentinel Dashboard代码,Nacos修改规则是可以同步到Sentinel的**,**但是通过Sentinel控制台修改或新增却不可以同步到Nacos。
  • 客户端数据源改为Nacos,客户端只需监听Nacos上配置变化。
  • 需要手动在Nacos上增改规则,Sentinel Dashboard上增改规则不会生效,也不会持久化到Nacos中。

客户端添加注解


<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-datasource-nacosartifactId>
dependency>

修改项目配置

  • sentinel.datasource注入类型为Map,所以flow作为key可以随便填写。
spring:
  application:
    name: sunnyws-service-example2
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 172.16.220.50:8848
        namespace: e90d261b-9c05-4bcb-b99f-b419d952737a
      config:
        server-addr: 172.16.220.50:8848
        file-extension: yml
        namespace: e90d261b-9c05-4bcb-b99f-b419d952737a
    sentinel:
      transport:
        #控制台地址
        dashboard: 172.16.220.50:8080
        port: 8917
      eager: true
      datasource:
      	#随便填写
        flow:
          nacos:
            server-addr: 172.16.220.50:8848
            dataId: ${spring.application.name}-flow-rules
            namespace: e90d261b-9c05-4bcb-b99f-b419d952737a
            data-type: json
            rule-type: flow
feign:
  sentinel:
    enabled: true

management:
  # 端点检查(健康检查)
  endpoints:
    web:
      exposure:
        include: "*"
ribbon:
  MaxAutoRetries: 0                     #(默认1次 不包括第一次)最大重试次数,当注册中心中可以找到服务,但是服务连不上时将会重试,如果注册中心中找不到服务则直接走断路器
  MaxAutoRetriesNextServer: 1           #(默认0次 不包括第一次)切换实例的重试次数
  OkToRetryOnAllOperations: false       #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
  ConnectTimeout: 4000                  #(默认1s)请求连接的超时时间
  ReadTimeout: 3000                     #(默认1s)请求处理的超时时间

Nacos Server添加配置文件

  • Data Id需要与配置文件中sentinel.datasource.xx.nacos.dataId相同

微服务实战(四) Sentinel 服务的限流 熔断 降级_第5张图片

添加配置

[
    {
        "app":"sunnyws-service-example2",
        "clusterConfig":{
            "acquireRefuseStrategy":0,
            "clientOfflineTime":2000,
            "fallbackToLocalWhenFail":true,
            "resourceTimeout":2000,
            "resourceTimeoutStrategy":0,
            "sampleCount":10,
            "strategy":0,
            "thresholdType":0,
            "windowIntervalMs":1000
        },
        "clusterMode":false,
        "controlBehavior":0,
        "count":100,
        "gmtCreate":1616226526395,
        "gmtModified":1616226526395,
        "grade":1,
        "id":1,
        "ip":"172.16.220.1",
        "limitApp":"default",
        "port":8917,
        "resource":"GET:http://sunnyws-service-example1/test",
        "strategy":0
    }
]
  • resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值
  • strategy:调用关系限流策略
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
  • clusterMode:是否为集群模式
  • 启动客户端,注册到nacos到,打开Sentinel Dashboard,可以看到上面nacos新建的限流规则。

微服务实战(四) Sentinel 服务的限流 熔断 降级_第6张图片

修改Sentinel Dashboard代码
  • 通过修改Sentinel Dashboard相关代码,将控制台数据源改为与客户端相同的Nacos,从Nacos上读取配置,并将控制台上规则变化持久化到Nacos上,实现与客户端数据的持久化与一致性。
  • 客户端配置与上面配置相同,只是Nacos中Sentinel 配置文件的Data Id与Group 需要修改。

下载源码包

  • 根据版本下载相应的版本包:https://github.com/alibaba/Sentinel/releases

修改配置

  • 修改Sentinel Dashboard模块pom.xml,注释test
<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-datasource-nacosartifactId>
    
dependency>

修改代码

  • test目录中sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos复制到sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos

微服务实战(四) Sentinel 服务的限流 熔断 降级_第7张图片

  • 需要修改代码文件

微服务实战(四) Sentinel 服务的限流 熔断 降级_第8张图片

  • 修改DashboardConfig增加配置项
/**
 * nacos server_addr
 */
public static final String CONFIG_NACOS_SERVER_ADDR = "sentinel.dashboard.nacos.server.addr";

/**
 * nacos namespace
 */
public static final String CONFIG_NACOS_SERVER_NAMESPACE = "sentinel.dashboard.nacos.server.namespace";

/**
 * nacos username
 */
public static final String CONFIG_NACOS_SERVER_USERNAME = "sentinel.dashboard.nacos.server.username";

/**
 * nacos password
 */
public static final String CONFIG_NACOS_SERVER_PASSWORD = "sentinel.dashboard.nacos.server.password";

public static String getConfigNacosServerAddr(){
    return getConfigStr(CONFIG_NACOS_SERVER_ADDR);
}

public static String getConfigNacosServerNamespace(){
    return getConfigStr(CONFIG_NACOS_SERVER_NAMESPACE);
}

public static String getConfigNacosServerUsername(){
    return getConfigStr(CONFIG_NACOS_SERVER_USERNAME);
}

public static String getConfigNacosServerPassword(){
    return getConfigStr(CONFIG_NACOS_SERVER_PASSWORD);
}
  • 修改NacosConfignacosConfigService
    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, DashboardConfig.getConfigNacosServerAddr());
        properties.put(PropertyKeyConst.NAMESPACE,DashboardConfig.getConfigNacosServerNamespace());
        properties.put(PropertyKeyConst.USERNAME,DashboardConfig.getConfigNacosServerUsername());
        properties.put(PropertyKeyConst.PASSWORD,DashboardConfig.getConfigNacosServerPassword());
        return ConfigFactory.createConfigService(properties);
    }
  • 修改FlowControllerV1

    • 注入Nacos流控规则

      微服务实战(四) Sentinel 服务的限流 熔断 降级_第9张图片

    • 新增Nacos publicshRules方法(将配置发布到配置中心Nacos)

      微服务实战(四) Sentinel 服务的限流 熔断 降级_第10张图片

    • 获取配置改为Nacos 上获取

      微服务实战(四) Sentinel 服务的限流 熔断 降级_第11张图片

    • 保存配置 改为持久化到Nacos

      微服务实战(四) Sentinel 服务的限流 熔断 降级_第12张图片

  • Nacos修改配置文件

    • Data Idapplication.name+-flow-rulesGroupSENTINEL_GROUP
    • 这是因为FlowRuleNacosProviderFlowRuleNacosPublisher中采用静态常量进行了初始化
    • 也可自定义修改静态常量GROUP_IDFLOW_DATA_ID_POSTFIX值,或和Nacos配置相同改为启动配置。

    微服务实战(四) Sentinel 服务的限流 熔断 降级_第13张图片

    微服务实战(四) Sentinel 服务的限流 熔断 降级_第14张图片

    微服务实战(四) Sentinel 服务的限流 熔断 降级_第15张图片

  • 重新部署和启动

#Dsentinel.dashboard.nacos.server.addr       Nacos 地址
#Dsentinel.dashboard.nacos.server.namespace  Nacos NameSpace
#Dsentinel.dashboard.nacos.server.username   Nacos用户名
#Dsentinel.dashboard.nacos.server.password   Nacos密码
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=172.16.220.50:8080 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.nacos.server.addr=172.16.220.50:8848 -Dsentinel.dashboard.nacos.server.namespace=e90d261b-9c05-4bcb-b99f-b419d952737a -Dsentinel.dashboard.nacos.server.username=nacos -Dsentinel.dashboard.nacos.server.password=nacos -jar sentinel-dashboard.jar
  • Dashboard新增流控规则,查看Nacos文件配置是否持久化

    微服务实战(四) Sentinel 服务的限流 熔断 降级_第16张图片

    微服务实战(四) Sentinel 服务的限流 熔断 降级_第17张图片

参考:https://www.jianshu.com/p/fb3218b21da5

作者: SunnyWs
链接: https://sunnyws.com/posts/104c04d2/
来源: SunnyWs’Blog

你可能感兴趣的:(微服务实战,spring,cloud,alibaba)