使用 Spring Cloud Alibaba Sentinel 的熔断降级保护微服务应用

1. 背景

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

1. Sentinel 介绍

Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。

1.1 知识

Sentinel 的组成:

  • (1) Sentinel 核心库, 即基本的类库的使用。
  • (2) Dashboard 控制台,即web页面的使用。

核心库介绍

本章节主要说 核心库 的使用。

使用 Sentinel 来进行资源保护,主要分为几个步骤:

  • 定义资源
  • 定义规则
  • 检验规则是否生效

也就是说:

  • 先把可能需要保护的资源定义好(即埋点)
  • 之后再配置规则,规则描述了什么方式来保护资源。
  • 声明了资源,后续在任何时候灵活地定义各种流量控制规则。

资源

资源:可以是指一个服务,一个服务里的方法,或者是一段代码。写代码时,考虑某段代码是否需要保护,如果需要就将之定义为一个资源。

定义资源的方式

sentinel 支持都多种方式来定义资源,常见的有:

  • 方式一:整合到常见的主流框架,比如 Web Servlet、Dubbo、Spring Cloud
  • 方式二:抛出异常的方式,使用 SphU 这个类的 try-catch 方式
  • 方式三:返回布尔值方式定义资源,使用 SphO 提供 if-else 风格的 API
  • 方式四:注解方式定义资源,使用 @SentinelResource 注解 。
  • 方式五:异步调用支持,使用 SphU.asyncEntry 异步方法。

示例有:
抛出异常的方式 来定义资源
使用 SphU 这个类的 try-catch 风格的 API。当“资源”发生了限流之后会抛出 BlockException,然后捕捉异常进行限流之后的逻辑处理。

示例代码如下:

try (Entry entry = SphU.entry("resourceName")) {
  // 被保护的业务逻辑
  // do something here...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级
  // 在此处进行相应的处理操作
}

规则

Sentinel 支持以下几种规则:

  • 流量控制规则
  • 熔断降级规则
  • 系统保护规则
  • 来源访问控制规则
  • 热点参数规则

流量控制规则(FlowRule)
支持 QPS 模式(1)或并发线程数模式(0)。

熔断降级规则(DegradeRule)
熔断策略,支持慢调用比例/异常比例/异常数策略

系统保护规则 (SystemRule)
结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡

来源访问控制规则 (AuthorityRule)
即黑名单,白名单规则。

规则的持久化
建议和 nacos 一起使用,方法见本文后面章节。

1.2 在service层使用 Sentinel

一般java web 项目都会有 controller 层, service 层,dao层,我们要在 service 层使用的是可以这么做。

(1)添加依赖

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

(2) 在服务层加注解:

@Service
public class TestService {

    @SentinelResource(value = "sayHello")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

@SentinelResource 注解用来标识资源是否被限流、降级。上述例子上该注解的属性 value 指示了一个资源名称。

@SentinelResource 还提供了其它额外的属性如 blockHandler,blockHandlerClass,fallback 用于表示限流或降级的操作

一般我们需要实现一个降级后的处理,比如上面的 fallback 指示一个降级后字符串返回值告知触发了熔断降级。

另外,Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。您只需要对应用进行简单的配置,就可以使用这些功能。我们在后面用一个章节来介绍它。

1.3 和 Feign 一起使用

Sentinel 适配了组件。

(1) 先引入 spring-cloud-starter-alibaba-sentinel 的依赖
(2) 再引入feign依赖
引入 spring-cloud-starter-openfeign 依赖**,使 Sentinel starter 中的自动化配置类生效:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(3) 配置文件打开
配置文件打开 Sentinel 对 Feign 的支持:

feign.sentinel.enabled=true

示例说明
比如下面的示例中你要了解的:

  • 1.正常的业务调用: /echo/{str}。
    1. 熔断后的异常处理,指定了 fallback 处理,并返回 "echo fallback" 字符串。

详细示例:

@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
public interface EchoService {
    @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
    String echo(@PathVariable("str") String str);
}

class FeignConfiguration {
    @Bean
    public EchoServiceFallback echoServiceFallback() {
        return new EchoServiceFallback();
    }
}

class EchoServiceFallback implements EchoService {
    @Override
    public String echo(@PathVariable("str") String str) {
        return "echo fallback";
    }
}

1.4 和 RestTemplate 一起使用

支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,加上 @SentinelRestTemplate 注解。

@Bean
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
    return new RestTemplate();
}

说明:@SentinelRestTemplate 注解的属性
@SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。

比如上面的示例指示了 ExceptionUtil.handleException 是熔断降级后的异常处理方法,该方面用明确的方法签名格式,如下:

public class ExceptionUtil {
    public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) {
        ...
    }
}

方法返回值提供了 SentinelClientHttpResponse 用于构造返回信息。

注意
应用启动的时候会检查 @SentinelRestTemplate 注解对应的限流或降级方法是否存在,如不存在会抛出异常

实际项目中也会在网关层使用,见下一章节。

2. 在 Spring Cloud Gateway 网关中使用

可以结合 Spring Cloud Gateway 一起使用。

  • (1) 添加 spring-cloud-alibaba-sentinel-gateway 依赖。
  • (2) 添加 spring-cloud-starter-gateway 依赖
    来让 spring-cloud-alibaba-sentinel-gateway 模块里的 Spring Cloud Gateway 自动化配置类生效:
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  • (3) 配置文件
    指定 spring.cloud.sentinel.filter.enabled 为 false

注意
网关流控规则数据源类型是 gw-flow,若将网关流控规则数据源指定为 flow 则不生效。

支持两种资源标识维度的限流
Sentinel 提供的 Spring Cloud Gateway 的适配模块可以提供两种资源维度的限流:

  • routeId:即在 gateway 中的路由 routeId。
  • 自定义分组的名称:可以利用 API 来自定义一些分组名,将URL归类在一个组下。
  • 默认不支持 URL 粒度

3. sentinel 的控制台

3.1 Sentinel 控制台包含如下功能:

  • 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
  • 监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
  • 规则管理和推送:统一管理推送规则。
  • 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。

3.2. 启动 sentinel 的控制台

下载最新版本的控制台 jar 包
可以从这个 release 页面 下载。

命令行启动

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar  -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456

说明:

  • -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080,浏览器从这个端访问。打开页面,默认用户名和密码都是 sentinel。

3.3. 规则管理

管理和新增规则
打开 http://localhost:8080
您可以在 控制台web页 配置修改规则,进行规则管理。

image.png

点击新增规则按钮,如下:


image.png

规则的存储
默认是存储在内存的,应用重启之后该规则会丢失。建议通过一些配置来使用外部存储方式来保存。建议结合 nacos 动态实时的刷新规则。

3.4. 规则推送

规则推送分为 3 种模式,包括:

  • 原始模式
  • Pull 模式
  • Push 模式"。

原始模式

通过 API 将规则推送至客户端并直接更新到内存中, 图例:

                             ------> sentinel 客户端1
Sentinel                     ------> sentinel 客户端2
Dashboard
                             ------> sentinel 客户端3

好处: 简单,无依赖;
坏处: 应用重启规则就会消失,不能用于生产环境

Pull模式

在客户端注册一个本地文件数据源:收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中。

本地文件数据源会定时轮询文件的变更,读取规则。

这样我们既可以在应用本地直接修改文件来更新规则,也可以通过 Sentinel 控制台推送规则。

以本地文件数据源为例,过程如下图所示:

                                      /---------- 在内存中更新规则(规则缓存)
                                     /
Sentinel        ----->   Sentinel客户端     ----> 将规则写入本地文件   ----> 本地文件
Dashboard

好处:简单,不引入新的依赖
坏处:无法保证监控数据的一致性

Push模式

Sentinel 控制台 的规则到 统一配置中心(比如nacos),再到各个 客户端。

即: Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel

图例:

                       nacos
             (1)    /        \
                   /           \    (2)
                 /               \
Sentinel                          |----    sentinel 客户端1
Dashboard                         |----    sentinel 客户端2

生产环境建议使用 PUSH 模式,改造方法见下一章节。

4. 和 nacos 集成

4.1 介绍

默认情况下,规则是存储在内存的,重启后就没了。因此在生产环境建议使用nacos 集成来使用。分成两个步骤:

  • (1) 在sentinel dashboard 控制台的web管理页面创建规则,并将规则存储到nacs。需要改造sentinel 控制台。
  • (2) 客户端应用获得从 nacos 推送(PUSH)而来的 “限流的配置规则”,并加载到sentinel中。

即:在sentinel dashboard 的web页设置限流规则 ---> 规则存储到 nacos ---> 再推送到客户端应用

4.2 改造 sentinel 控制台

改造的目标是:改造 sentinel 控制台,使得在控制台的web页修改的规则保存到nacos中去。
具体改造方法:略。
有同学已经改造好的在这里:https://gitee.com/schonglin/sentinel-nacos

4.3 配置客户端,读nacos数据源。

实现的目标是:从nacos 读取规则并应用到客户端应用中。

4.3.1 修改客户端服务的配置文件,添加一个数据源

下面的示例中,我添加了一个 sentinel 的数据源 ds2, 指定了 nacos服务的地址,data-id 配置文件名,规则是 rule-type 限流类型。

spring:
  application:
    name: business
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080 # 指定控制台地址和端口
        port: 8721 # 这个端口和 Sentinel dashborad 做交互
      datasource:
        # 指定一个用于流控规则的数据源(来自nacos)
        ds2:
          nacos:
            server-addr: ${spring.cloud.nacos.discovery.server-addr}
            data-id: ${spring.application.name}-flow-rules  # 比如流控的规则是 {appName}-flow-rules
            group-id: SENTINEL_GROUP # 指定的一个分组名
            data-type: json
            rule-type: flow

4.3.2 在nacos中添加一个限流的配置文件,和数据源名称一致

我在nacos中添加一个限流的配置文件,名字叫做${spring.application.name}-sentinel-flow,它的格式和上面 data-id 要对应上。

[
    {
        "resource": "/hello",
        "limitApp": "default",
        "grade": 1,
        "count": 6,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

上面的配置内容说明:

  • resource:资源名
  • limitApp:调用来源, default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值,和上面的类型相关
  • strategy:调用关系限流策略
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
  • clusterMode:是否为集群模式

访问几次接口后,就可以在Sentinel Dashboard 中看到在nacos中配置的规则信息,重启后也可以再次重nacos获取到配置好的规则。

我的示例demo 见: https://github.com/vir56k/java_demo/tree/master/sentinel/sentineldemo3 配合 改造后支持nacos的sentinel 来使用。

5. 参考

Sentinel 控制台
https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel
https://www.cnblogs.com/gyli20170901/p/11279576.html
https://github.com/alibaba/Sentinel/wiki/Sentinel-%E6%8E%A7%E5%88%B6%E5%8F%B0%EF%BC%88%E9%9B%86%E7%BE%A4%E6%B5%81%E6%8E%A7%E7%AE%A1%E7%90%86%EF%BC%89#%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE
https://blog.csdn.net/qq_38723394/article/details/108991518

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容