【SpringCloud】使用 Spring Cloud Alibaba 之 Sentinel 实现微服务的限流、降级、熔断

目录

    • 一、Sentinel 介绍
      • 1.1 什么是 Sentinel
      • 1.2 Sentinel 特性
      • 1.3 限流、降级与熔断的区别
    • 二、实战演示
      • 2.1 下载启动 Sentinel 控制台
      • 2.2 后端微服务接入 Sentinel 控制台
        • 2.2.1 引入 Sentinel 依赖
        • 2.2.2 添加 Sentinel 连接配置
      • 2.3 使用 Sentinel 进行流控(含限流)
        • 2.3.1 对接口添加 Sentinel 资源标记
        • 2.3.2 Sentinel 的流控模式
        • 2.3.3 Sentinel 的流控效果
        • 2.3.4 直接流控演示
        • 2.3.5 关联流控演示
        • 2.3.6 根据调用源对接口限流
          • 1. 给请求打标
          • 2. 解析请求源
          • 3. 下发限流规则
      • 2.4 使用 Sentinel 实现降级、熔断
        • 2.4.1 Sentinel 中的熔断策略
        • 2.4.2 实现降级、熔断
          • 1. 核心思路
          • 2. 降级实现
          • 3. 熔断策略

一、Sentinel 介绍

1.1 什么是 Sentinel

  • Sentinel 对开发者的大概印象应该是阿里开源的一个SpringCloud 组件,用来做微服务的限流、降级和熔断。这也是本文从概念和实战上主要的展开点。
  • 官方点的话说就是: Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。

在这里插入图片描述

1.2 Sentinel 特性

官方总结了 Sentinel 组件的4大特性,概括了 Sentinel 组件提供的能力:

  • 丰富的应用场景:阿里巴巴 10 年双十一积累的丰富流量场景,包括秒杀、双十一零点持续洪峰、热点商品探测、预热、消息队列削峰填谷等多样化的场景;
  • 易于使用,快速接入:简单易用,开源生态广泛,针对 Dubbo、Spring Cloud、gRPC、Zuul、Reactor、Quarkus 等框架只需要引入适配模块即可快速接入;
  • 多样化的流量控制:资源粒度、调用关系、指标类型、控制效果等多维度的流量控制;
  • 可视化的监控和规则管理:简单易用的 Sentinel 控制台;

Sentinel特性概览

1.3 限流、降级与熔断的区别

  • 限流是在流量进入到系统内之前,先进行一个统计计算,如果已经超过设定的阈值,则直接拒绝当前的请求,那么当前流量不会进入服务的内部;
  • 降级指的是如果在执行一个请求的调用时,如果发生了异常,那么请求就会继续执行指定的降级逻辑。此时,请求已经进入到了服务内部;
  • 熔断是对一个时间窗口内处理的请求的结果进行统计后,如果这批请求的错误率达到了阈值(或者慢接口比例达到了阈值),则会触发一个指定时间段长度的熔断;
    服务的限流、降级、熔断这三板斧的结合在很大程度上抑制了服务雪崩的发生。

二、实战演示

2.1 下载启动 Sentinel 控制台

我们到 Sentinel 官方的 Github 上下载 sentinel-dashboard 服务的 Jar 包,Sentinel 服务的限流、熔断等规则的下发就是通过 sentinel-dashboard 来进行的,下载链接。当前的最新版本是1.8.7。

在这里插入图片描述
sentinel-dashboard 的 Jar 包下载完毕后,把它放在合适的目录,使用如下命令启动Jar包:

java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.7.jar

然后在浏览器的地址框内输入 http://localhost:8888/ 会进入 Sentinel 控制台的登陆界面:

在这里插入图片描述

默认的用户名和密码都是 sentinel,输入后即可进入 Sentinel 控制台主界面:

在这里插入图片描述

2.2 后端微服务接入 Sentinel 控制台

2.2.1 引入 Sentinel 依赖

在我们需要使用 Sentinel 组件的后端微服务中先引入 Sentinel 的依赖:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.2.2 添加 Sentinel 连接配置

如果要想将后端微服务对接到 Sentinel 控制台,除了要添加 Sentinel 依赖以外,还需要在配置文件中添加上 Sentinel 控制台相关的配置信息,主要是为了配置Sentinel 控制台的访问地址,此处配置的本地访问端口号为8888。

spring:cloud:sentinel:transport:# sentinel 的默认端口号为 8719port: 8719# dashboard地址dashboard: localhost:8888

2.3 使用 Sentinel 进行流控(含限流)

2.3.1 对接口添加 Sentinel 资源标记

对于 Sentinel 组件来说,一切的 API 接口都是资源,Sentinel 的职责就是在流量到来时,根据这些 Sentinel 资源的负载情况对流量进行管理。所以,我们需要先对代码中定义的 API 接口打上 Sentinel 资源的标记。Sentinel 是通过 @SentinelResource 注解对 API 接口打标记的。下面以2个获取商品的接口为例演示下用法。

	@GetMapping("/getGoods")@SentinelResource(value = "getGoods")public CoinGoodsInfo getGoods(@RequestParam("id") Long id){log.info("Get goods, id={}", id);return coinGoodsService.getGoodsInfo(id);}// 批量获取@GetMapping("/getBatch")@SentinelResource(value = "getGoodsInBatch")public Map<Long, CoinGoodsInfo> getGoodsInBatch(@RequestParam("ids") Collection<Long> ids) {log.info("getGoodsInBatch: {}", JSON.toJSONString(ids));return coinGoodsService.getGoodsInfoMap(ids);}
2.3.2 Sentinel 的流控模式

在使用 Sentinel 演示具体的流控之前,先简单的介绍下 Sentinel 的流控。Sentinel 的进行流量控制时分为3种模式:直接流控,关联流控,链路流控。

  • 直接流控:进行流量管理时直接作用于目标 Sentinel 资源,如果当前的访问压力大于预先设定的阈值,直接拦截当前的请求;
  • 关联流控:在关联流控中,Sentinel 资源中存在一个优先级的概念,同时他们会共享某个资源,比如都依赖某个接口或者共享一个数据库连接池。当高优先级的 Sentinel 资源的访问流量达到了设定阈值时,会对低优先级的 Sentinel 资源接口进行限流。
  • 链路流控:当指定链路上的访问量大于某个阈值时,对当前资源进行限流。
2.3.3 Sentinel 的流控效果

Sentinel 目前提供了 3 种流控效果,分别是:快速失败,Warm-up,排队等待。

  • 快速失败:当某个 Sentinel 资源的访问流量超过了设定的阈值, 后面的请求会直接被拦截住;
  • Warm-up:该模式下系统承载的流量有一个缓慢拉高的过程,而不是一开始就将系统承载的流量设置为最高可承受的流量。假设我们设置的系统QPS阈值是100,预热时间为5秒,那么 Sentinel 会在 5 秒内逐渐的将限流阈值从33 拉高到 100。因为 Sentinel 内部有一个冷加载因子,取值为3。100/3=33。因此初始的限流阈值为33。
  • 排队等待:如果当前的流量已经超过了接口设定的阈值,超出部分的请求会被放到队列中,等到系统的请求量下来,再将请求交给系统处理。同时,注意被放入到队列的请求有一个超时等待时间,如果被放入到队列的请求在队列中滞留的时间过长,该请求会被丢弃。
2.3.4 直接流控演示

首先,我们需要在代码中先指定请求被限流时,要执行的限流逻辑。该限流部分的逻辑指定,需要我们先定义对应的降级方法,然后在 @SentinelResource 注解中的 blockHandler 属性绑定降级方法的方法名即可。

	@GetMapping("/getGoods")@SentinelResource(value = "getGoods", blockHandler = "getGoods_block")public CoinGoodsInfo getGoods(@RequestParam("id") Long id){log.info("Get goods, id={}", id);return coinGoodsService.getGoodsInfo(id);}public CoinGoodsInfo getGoods_block(Long id){log.info("Calling limited, id={}", id);return null;}// 批量获取@GetMapping("/getBatch")@SentinelResource(value = "getGoodsInBatch",fallback = "getGoodsInBatch_fallback",blockHandler = "getGoodsInBatch_block")public Map<Long, CoinGoodsInfo> getGoodsInBatch(@RequestParam("ids") Collection<Long> ids) {log.info("getGoodsInBatch: {}", JSON.toJSONString(ids));return coinGoodsService.getGoodsInfoMap(ids);}

如上的 /getGoods 接口,该接口因限流调用失败时,会执行 blockHandler 属性绑定的 getGoods_block 方法,返回 null

下面我们在代码中演示下直接流控。直接流控的配置如下图:

在这里插入图片描述

资源名:就是我们使用 @SentinelResource 注解时,value 属性指定的值。
阈值类型:选QPS,表示请求的QPS(Query per second),这里我们设置的阈值为1。
流控模式:选“直接”
流控效果:可以选“快速失败”,也可以选择其他选项,“快速失败”简单直接,用postman 等工具测试时可以直接看到效果。

点击“新增”,这条流控规则就新增完毕了。

在 postman 中调用相应的接口,点的快一点,保证1秒内超过1次,可以看到打印的日志,确实是走了限流逻辑的。

在这里插入图片描述

2.3.5 关联流控演示

接下来我们还是利用在 2.3.4 中的代码实现。假设2个接口/getGoods/getBatch 存在资源竞争关系,然后我们在 Sentinel 控制台中配置关联流控的规则,其具体的配置项如下图:

在这里插入图片描述
这里设置流控规则时,设置的资源名为 getGoodsInBatch ,关联到的sentinel资源是getGoods ,设置的 QPS=1。意思就是 Sentinel 资源 getGoods (/getGoods 接口)的访问QPS为1时,就会触发对 Sentinel 资源getGoodsInBatch/getBatch 接口)的限流。

2.3.6 根据调用源对接口限流

背景:这种情况就是,假设有3个微服务A,B,C,微服务A,B 都依赖微服务C,都需要调用微服务C 的接口。而且对于A, B 这2个微服务来说,A 是核心业务,B 是边缘业务。现在我们在使用Sentinel 对微服务 C 中的某接口进行限流时,需要识别这个请求是来自微服务A 还是 B。在业务的高峰期,我们需要对来自微服务B 的请求进行限流。

核心思路主要分为3个步骤:

  1. 服务消费者在下发请求时,对请求打标,表明请求来源。在微服务内使用拦截器,对所有的请求加上统一的header即可;
  2. 服务提供者在处理请求是需要处理Request,识别Request 来源。实现 Sentinel 提供的 RequestOriginParser 接口,获取Request中的请求源标记;
  3. 在下发限流规则时需要指定请求源服务注册发现时上报的服务名,并配置其它的限流规则;

下面我们来一一实现。

1. 给请求打标

因为我微服务间调用使用的是 Feign,所以这里我实现 FeignRequestInterceptor 接口完成一个拦截器,为所有的请求统一加上 Header。

@Configuration
public class SentinelInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {template.header("SentinelSource", "coin-customer-src");}
}
2. 解析请求源

实现 Sentinel 提供的 RequestOriginParser 接口,获取Request中的请求源标记。

@Component
public class SentinelOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest request) {return request.getHeader("SentinelSource");}
}
3. 下发限流规则

下发新的限流规则,针对来源不再是default 变成了 microservice-A ,这意味着当请求流量达到设定阈值时,限流的拦截只对该微服务生效。
在这里插入图片描述

2.4 使用 Sentinel 实现降级、熔断

2.4.1 Sentinel 中的熔断策略

Sentinel 中有3种熔断策略指标:慢调用比例,异常比例,异常数。

  1. 慢调用比例:该场景下会统计每个调用的RT(Response Time),是否会超过设定的阈值,在统计的时间窗口内如果慢调用的比例超过了阈值,则会进行熔断;
  2. 异常比例:选择了异常比例策略,Sentinel 会统计每个接口调用发生异常的情况,如果,如果调用发生异常的情况占总调用的比例超过设定阈值,就会触发熔断;
  3. 异常数:就是会计算当前时间窗口内所有接口调用的异常情况,如果调用失败次数超过了设定的阈值,就会触发熔断;
2.4.2 实现降级、熔断
1. 核心思路

因为我们在选定了熔断策略之后,当服务触发了熔断,熔断期间,接口就会走降级策略。所以,首先,需要在代码中实现降级逻辑;其次,需要在 Sentinel 控制台添加熔断策略。

2. 降级实现

接下来我们在2个接口的 @SentinelResource 注解中,使用 fallback 属性绑定我们实现了降级逻辑的降级方法。

	@GetMapping("/getGoods")@SentinelResource(value = "getGoods", fallback="getGoods_fallback", blockHandler = "getGoods_block")public CoinGoodsInfo getGoods(@RequestParam("id") Long id){log.info("Get goods, id={}", id);return coinGoodsService.getGoodsInfo(id);}public CoinGoodsInfo getGoods_block(Long id){log.info("Calling limited, id={}", id);return null;}public CoinGoodsInfo getGoods_fallback(Long id) {log.info("Calling fallback, id={}", id);return null;}// 批量@GetMapping("/getBatch")@SentinelResource(value = "getGoodsInBatch",fallback = "getGoodsInBatch_fallback",blockHandler = "getGoodsInBatch_block")public Map<Long, CoinGoodsInfo> getGoodsInBatch(@RequestParam("ids") Collection<Long> ids) {log.info("getGoodsInBatch: {}", JSON.toJSONString(ids));return coinGoodsService.getGoodsInfoMap(ids);}public Map<Long, CoinGoodsInfo> getGoodsInBatch_fallback(Collection<Long> ids) {log.info("Calling fallback, ids={}", ids.toString());return new HashMap<>();}public Map<Long, CoinGoodsInfo> getGoodsInBatch_block(Collection<Long> ids, BlockException exception) {log.info("calling is limited, ids: {}, exception: ", ids, exception);return new HashMap<>();}
3. 熔断策略

我们在 Sentinel 控制台中添加熔断规则如下,对 Sentinel 资源 getGoods 添加熔断规则,熔断策略选择“异常比例”,设置的比例阈值为 0.4 ,熔断时长为10秒,最小请求数为50,统计时长为10000毫秒。结合起来就是在 10000毫秒的时间窗口内统计所有的请求,当时间窗内的请求数大于50个,且请求失败率大于40%时,会触发一个10秒的熔断。 熔断期间会执行我们代码中定义的降级逻辑。

在这里插入图片描述

启动服务,调用/getGoods 接口,可以看到确实是走了降级逻辑的。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/696502.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何将cocos2d-x js打包部署到ios上 Mac M1系统

项目环境 cocos2d-x 3.13 xcode 12 mac m1 big sur 先找到你的项目 使用xcode软件打开上面这个文件 打开后应该是这个样子 执行编译运行就好了 可能会碰到的错误 在xcode11版本以上都会有这个错误&#xff0c;这是因为iOS11废弃了system。 将上面代码修改为 #if (CC_TARGE…

Java 面向对象进阶 16 接口的细节:成员特点和接口的各种关系(黑马)

成员变量默认修饰符是public static final的原因是&#xff1a; Java中接口中成员变量默认修饰符是public static final的原因是为了确保接口的成员变量都是公共的、静态的和不可修改的。 - public修饰符确保了接口的成员变量可以在任何地方被访问到。 - static修饰符使得接口…

vue-利用属性(v-if)控制表单(el-form-item)显示/隐藏

表单控制属性 v-if 示例&#xff1a; 通过switch组件作为开关&#xff0c;控制表单的显示与隐藏 <el-form-item label"创建数据集"><el-switch v-model"selectFormVisible"></el-switch></el-form-item><el-form-item label&…

Redis篇----第七篇

系列文章目录 文章目录 系列文章目录前言一、Redis 的回收策略(淘汰策略)?二、为什么 edis 需要把所有数据放到内存中?三、Redis 的同步机制了解么?四、Pipeline 有什么好处,为什么要用 pipeline?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍…

crontab history查看命令的执行时间

crontab crontab学习网站&#xff08;19. crontab 定时任务 — Linux Tools Quick Tutorial&#xff09; 例子 今天实际工作里用到的&#xff08;已经进行了防信息泄露处理 比如我现在希望每周三上午10:00之行一个php脚本 --gpt生成 00 10 * * 3 cd /home/user/project/r…

阿里云SSL免费证书到期自动申请部署程序

阿里云的免费证书只有3个月的有效期&#xff0c;不注意就过期了&#xff0c;还要手动申请然后部署&#xff0c;很是麻烦&#xff0c;于是写了这个小工具。上班期间抽空写的&#xff0c;没有仔细测试&#xff0c;可能存在一些问题&#xff0c;大家可以自己clone代码改改&#xf…

【大模型 数据增强】LLMAAA:使用 LLMs 作为数据标注器

【大模型 数据增强】LLMAAA&#xff1a;使用 LLMs 作为数据标注器 提出背景算法步骤1. LLM作为活跃标注者&#xff08;LLMAAA&#xff09;2. k-NN示例检索与标签表述化3. 活跃学习策略4. 自动重权技术 LLMAAA 框架1. LLM Annotator2. Active Acquisition3. Robust Training 总结…

SkyWalking之APM无侵入可观测原理分析

一、 简介&#xff08;为什么需要用到可观测能力&#xff09; 随着微服务的开发模式的兴起&#xff0c;早期的单体架构系统已拆分为很多的子系统&#xff0c;各个子系统封装为微服务&#xff0c;各服务间通过HTTP协议RESET API或者RPC协议进行调用。 在单体服务或者微服务较少的…

8:00面试,8:05就出来了 ,问的实在是....

从外包出来&#xff0c;没想到竟然死在了另一家厂子 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以我也就忍了。没想到12月一纸通知&#xff0c;所有人都不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个…

ESP8266智能家居(2)——8266发布数据到mqtt服务器

1.公共服务器 学习物联网就离不开服务器&#xff0c;如果你资金充足的话&#xff0c;可以自己购买或者租用一个服务器。本次我选择&#xff0c;使用免费的公共MQTT服务器。它的端口及Broker信息如下&#xff1a; 网址为&#xff1a; 免费的公共 MQTT 服务器 | EMQ (emqx.com)h…

LLMChain使用 | RouterChain的使用 - 用本地大模型搭建多Agents

单个本地大模型搭建参考博客 单个Chain&#xff1a;面对一个需求&#xff0c;我们需要创建一个llmchain&#xff0c;设置一个prompt模板&#xff0c;这个chain能够接收一个用户input&#xff0c;并输出一个结果&#xff1b;多个Chain&#xff1a;考虑到同时面对多个需求&#x…

第三百六十回

文章目录 1. 概念介绍2. 实现方法2.1 环绕效果2.2 立体效果 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义SlideImageSwitch组件"相关的内容&#xff0c;本章回中将介绍两种阴影效果.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本…

设计模式-创建型模式-原型模式

原型模式&#xff08;Prototype Pattern&#xff09;&#xff1a;使用原型实例指定创建对象的种类&#xff0c;并且通过克隆这些原型创建新的对象。原型模式是一种对象创建型模式。原型模式其实就是从一个对象再创建另外一个可定制的对象&#xff0c;而且不需知道任何创建的细节…

微信小程序开发学习笔记——2.8媒体组件image的src三种引入方式

>>跟着b站up主“咸虾米_”学习微信小程序开发中&#xff0c;把学习记录存到这方便后续查找。 课程连接&#xff1a; https://www.bilibili.com/video/BV19G4y1K74d?p11 image&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/component/image.html 一…

Redis-内存管理

Redis是基于内存存储的&#xff0c;非关系型&#xff0c;键值对数据库。因此&#xff0c;对Redis来说&#xff0c;内存空间的管理至关重要。那Redis是如何内存管理的呢&#xff1f; 一、最大内存限制 Redis 提供了 maxmemory 参数允许用户设置 Redis 可以使用的最大内存大小。…

js设计模式:依赖注入模式

作用: 在对象外部完成两个对象的注入绑定等操作 这样可以将代码解耦,方便维护和扩展 vue中使用use注册其他插件就是在外部创建依赖关系的 示例: class App{constructor(appName,appFun){this.appName appNamethis.appFun appFun}}class Phone{constructor(app) {this.nam…

Elastic Search:构建语义搜索体验

当你逐步熟悉 Elastic 时&#xff0c;你将使用 Elasticsearch Relevance Engine™ (ESRE)&#xff0c;该引擎旨在为 AI 搜索应用程序提供支持。 借助 ESRE&#xff0c;你可以利用一套开发人员工具&#xff0c;包括 Elastic 的文本搜索、向量数据库和我们用于语义搜索的专有转换…

ngnix网站服务详解

一 Nginx的简介 1 Nginx&#xff1a; ①Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热…

2月22日作业,按键中断LED灯控制

1.使用GPIO子系统&#xff0c;编写LED驱动&#xff0c;应用程序测试 mychrdev.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/of.h> …

微软Azure OpenAI的 GPT 接口使用小结

直接使用OpenAI的 GPT服务&#xff0c;在国内环境使用上会一些相关问题&#xff0c;微软提供了OpenAI的服务&#xff0c;基本上可以满足的相关的需要。下面提供一些简单的使用操作&#xff0c;来让你快速使用到 GPT 的服务。 前提&#xff1a;注册Azure的账户&#xff0c;并绑…