spring cloud之集成sentinel

写在前面

源码 。
本文一起看下spring cloud的sentinel组件的使用。

1:准备

1.1:理论

对于一个系统来说,最重要的就是高可用,那么如何实现高可用呢?你可能会说,集群部署不就可以了,但事实并非这么简单,假定一个不那么靠谱的开发,写了一个不那么靠谱的sql语句,上线之后,DB资源很快耗尽,那么所有需要查询DB的服务都无法处理请求,进而导致这些服务挂掉,而上游的服务因为无法快速得到响应,也会很快的挂掉,进而整个系统都会无法对外提供服务,这其实就是发生了非常可怕的服务雪崩,这个过程可以简单参考下图:
在这里插入图片描述
假定那个不那么靠谱的开发,是在服务D开发了那个不那么靠谱的sql语句,则上线后的后果就是D导致B和C不可用,B和C的不可用又会导致A的不可用,最终整个系统不可用。所以想要真正的实现高可用,除了多节点的集群部署外,我们还需要预防服务雪崩,而本文要学习的sentinel正是这样的一个组件,我们可以叫做容错组件

基本上,导致服务雪崩发生的原因在2个方面,第一个方面是高并发导致的请求量增大,第二方面就是应用内部的异常和错误(就像那个不那么靠谱的sql)。其实sentinel也正是从这两方面来预防服务雪崩的,对于高并发,sentinel可以从外部来限制并发量,对于应用内部异常和错误,sentinel可以进行降级和熔断。我们也会从这方面来展开sentinel的实战环节。

在java中,万物皆对象,在Linux中,万物皆文件,而在sentinel中,万物皆资源,而这里的资源我们可以认为就是接口地址,而对这些资源作用的过程是通过其内部的一个责任链,可以参考下图:
在这里插入图片描述
比如有用来收集数据的StaticSlot,构建调用链的NodeSelectorSlot(形成一个树状的调用关系图),如果业务有需要,我们也可以增加自定义的额slot到这个调用链上。

1.2:安装sentinel

首先在这里 下载可运行的jar包,接着如下操作:

$ java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar
INFO: Sentinel log output type is: file
INFO: Sentinel log charset is: utf-8
INFO: Sentinel log base directory is: C:\Users\dell9020\logs\csp\
INFO: Sentinel log name use pid is: false.   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v2.0.5.RELEASE)...

成功后访问http://localhost:8080/#/login,进入登陆页面:
在这里插入图片描述
账号sentinel/sentinel,成功后进入如下页面:
在这里插入图片描述

2:限流实战

限流,或者叫流量整形,是sentinel从外部预防服务雪崩的重要手段。

2.1:基础配置

这部分我们直接来使用sentiniel对我们项目做流量整形,首先,在custom和template模块引入依赖:

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

然后在custom和template模块的application.yml中配置sentinel信息:

spring:jpa:...cloud:sentinel:eager: true transport:port: 8719dashboard: localhost:8080

接着使用@SentinelResource注解标记要进行流量整形的接口,如下:

  • custom模块
dongshi.daddy.sentinel.controller.CouponCustomerController#requestCoupon
@PostMapping("requestCoupon")
@SentinelResource(value = "requestCoupon")
public Coupon requestCoupon(@Valid @RequestBody RequestCoupon request) {...
}
@PostMapping("findCoupon")
@SentinelResource(value = "customer-findCoupon")
public List<CouponInfo> findCoupon(@Valid @RequestBody SearchCoupon request) {return customerService.findCoupon(request);
}
  • template模块
// 读取优惠券
@GetMapping("/getTemplate")
@SentinelResource(value = "getTemplate")
public CouponTemplateInfo getTemplate(@RequestParam("id") Long id){log.info("Load template, id={}", id);/*try {// 休眠二十秒模拟超时TimeUnit.SECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}*/return couponTemplateService.loadTemplateInfo(id);
}// 批量获取
@GetMapping("/getBatch")
// 降级要执行的方法
@SentinelResource(value = "getTemplateInBatch", blockHandler = "getTemplateInBatch_block")
public Map<Long, CouponTemplateInfo> getTemplateInBatch(@RequestParam("ids") Collection<Long> ids) {log.info("getTemplateInBatch: {}", JSON.toJSONString(ids));return couponTemplateService.getTemplateInfoMap(ids);
}
// 降级要执行的方法
public Map<Long, CouponTemplateInfo> getTemplateInBatch_block(Collection<Long> ids, BlockException exception) {log.info("接口被限流");return Maps.newHashMap();
}

接着我们启动服务,如果一切正常的话,就可以看到custom和template这两个模块注册到sentinel上了:
在这里插入图片描述

2.2:通过流控规则进行限流

sentinel支持通过三种方式来进行流量整形:

直接流控:针对特定接口(sentinel称为资源)限流
关联流控:当某接口(sentinel称为资源)达到限流条件时对关联的接口(sentinel称为资源)进行限流
链路流控:

2.2.1:直接流控

我们对资源getTemplateInBatch进行流控,在sentinel选择template对应的微服务,点击子菜单流控规则,然后点击右上角在这里插入图片描述 添加流控规则,如下:
在这里插入图片描述

为了测试我们使用jmeter来进行测试,jmeter配置可以从这里 下载,配置如下:
在这里插入图片描述
通过按钮在这里插入图片描述 启动,之后查看template模块日志输出如下:

2024-01-08 15:34:44.411  INFO 26504 --- [io-20006-exec-7] d.d.s.c.CouponTemplateController         : getTemplateInBatch: [2,3]
Hibernate: select coupontemp0_.id as id1_0_, coupontemp0_.available as availabl2_0_, coupontemp0_.type as type3_0_, coupontemp0_.created_time as created_4_0_, coupontemp0_.description as descript5_0_, coupontemp0_.name as name6_0_, coupontemp0_.rule as rule7_0_, coupontemp0_.shop_id as shop_id8_0_ from coupon_template coupontemp0_ where coupontemp0_.id in (? , ?)
2024-01-08 15:34:44.904  INFO 26504 --- [io-20006-exec-5] d.d.s.c.CouponTemplateController         : 接口被限流

可以看到第二次执行了熔断逻辑被限流了。

2.2.2:关联流控

jmeter配置下载 。

我们来设置当getTempalte接口qps超过1时限制getBatch接口,配置如下:
在这里插入图片描述
首先我们使用jmeter模拟qps 2不间断访问getTemplate接口,如下:
在这里插入图片描述
启动后,这样,肯定就会触发限流规则了,这样,我们先来启动jmeter,
在这里插入图片描述
之后访问getBatch接口,如下:

http://localhost:20006/template/getBatch?ids=2,3

在这里插入图片描述
查看后台输出:
在这里插入图片描述
然后我们来停止jmeter,再来请求接口,就会恢复正常了:
在这里插入图片描述

2.2.3:链路流控

jmeter配置下载 。
对于同一个资源访问可以来自于不同的链路,针对特定的链路进行流控,就是链路流控了,如下图,上方链路就是被流控的:
在这里插入图片描述

在这里插入图片描述
这里我们模拟从custom模块访问template模块的getBatch接口,为了测试,需要首先在custom模块中增加如下接口:

// 批量获取
@GetMapping("/getBatchFromCustomer")
public Map<Long, CouponTemplateInfo> getTemplateInBatch(@RequestParam("ids") Collection<Long> ids) {log.info("getTemplateInBatch111: {}", JSON.toJSONString(ids));return templateService.getTemplateInBatch(ids);
}

因为需要进行限流的资源需要知道当前的调用者是谁,才能知道是否需要触发,所以,首先需要在custom模块添加openfeign的拦截器,在openfeign的请求中添加来源头

@Configuration
public class OpenfeignSentinelInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {template.header("SentinelSource", "coupon-customer-serv");}
}

接着在tempalte模块中获取这个来源的信息:

@Component
@Slf4j
public class SentinelOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest request) {log.info("request {}, header={}", request.getParameterMap(), request.getHeaderNames());return request.getHeader("SentinelSource");}
}

接着我们来配置sentinel针对来源coupon-customer-serv进行限流,如下:
在这里插入图片描述
接着开启jmeter,正常的话会看到被限流了:
在这里插入图片描述
为了测试来源不匹配的情况不限流,我们将sentinel的目标资源名称随便改为其他的,如下:
在这里插入图片描述
此时再开启jmeter测试就正常了:
在这里插入图片描述

2.3:三种流控效果

sentinel支持三种流控效果,快速失败,warm up,排队等待,在上述的实战环节我们使用就是快速失败,这也是sentinel默认的流控效果。

  • 快速失败
    直接失败。
  • warm up
    这是一种从低水位逐渐拉高的一种限流方式,比如如下的配置:
    在这里插入图片描述
    上图设置在5秒内拉高到10进行限流,而非开始就是10,开始的限流值需要除以冷却因子,这里冷却因子是3,所以就是10/3=3,也就是当qps到达3时开始限流,然后在5秒内将这个限流值拉高到最大值10,
    在这里插入图片描述

使用的场景,如采用缓存+DB读的场景,如果接口一段时间内都处于很低的水位,导致大量的缓存都失效了,此时突然发生了突发流量(某明星出轨了,某漂亮country被原子弹攻击了),此时缓存还没有完全构建起来,为了避免突发流量全部打到DB,把DB打穿,就可以考虑使用warm up,在一段时间内从低水位逐渐拉到高水位,同时在这段时间内完成缓存的构建工作。

  • 排队等待
    被限流的请求在一个任务队列中排队等待,并按照超时等待时间从队列中删除任务,如下500内还没有处理则移除任务的配置:
    在这里插入图片描述

3:降级、熔断实战

jmeter配置 。
降级、熔断,是sentinel从服务内部预防服务雪崩的重要手段。这部分我们一起来看下如何使用sentinel来实现降级和熔断。为了方便测试我们首先在template模块添加一个新的接口并设置为sentinel的资源:

// 批量获取
@GetMapping("/getBatchV1")
// 降级要执行的方法
@SentinelResource(value = "getTemplateInBatchV1", fallback = "getTemplateInBatch_fallback")
public Map<Long, CouponTemplateInfo> getTemplateInBatchV1(@RequestParam("ids") Collection<Long> ids) {log.info("getTemplateInBatch: {}", JSON.toJSONString(ids));int i = 1 / 0;return couponTemplateService.getTemplateInfoMap(ids);
}public Map<Long, CouponTemplateInfo> getTemplateInBatch_fallback(Collection<Long> ids) {log.info("接口被fallback");return Maps.newHashMap();
}

这里注意指定了fallback = "getTemplateInBatch_fallback",则当抛出了RuntimeException时就会进入执行降级逻辑,接着我们就需要在sentinel中配置熔断逻辑了,如下:
在这里插入图片描述
降级熔断的判断过程可以参考下图(注意时示例)
在这里插入图片描述
接着执行jemter,日志输出如下:

2024-01-10 14:01:47.813  INFO 13112 --- [io-20006-exec-2] d.d.s.c.CouponTemplateController         : getTemplateInBatch: [2,3] #
2024-01-10 14:01:47.813  INFO 13112 --- [io-20006-exec-2] d.d.s.c.CouponTemplateController         : 接口被fallback 
2024-01-10 14:01:47.813  INFO 13112 --- [o-20006-exec-10] d.daddy.sentinel.SentinelOriginParser    : request org.apache.catalina.util.ParameterMap@39d7b9e0, header=org.apache.tomcat.util.http.NamesEnumerator@7d50964c
2024-01-10 14:01:47.814  INFO 13112 --- [o-20006-exec-10] d.d.s.c.CouponTemplateController         : 接口被fallback
2024-01-10 14:01:47.815  INFO 13112 --- [io-20006-exec-9] d.daddy.sentinel.SentinelOriginParser    : request org.apache.catalina.util.ParameterMap@39d7b9e0, header=org.apache.tomcat.util.http.NamesEnumerator@1f47105b
2024-01-10 14:01:47.816  INFO 13112 --- [io-20006-exec-9] d.d.s.c.CouponTemplateController         : 接口被fallback
....
2024-01-10 14:01:47.813  INFO 13112 --- [io-20006-exec-2] d.d.s.c.CouponTemplateController         : getTemplateInBatch: [2,3] # 1s后半开启,后又重新进入熔断
2024-01-10 14:01:47.813  INFO 13112 --- [io-20006-exec-2] d.d.s.c.CouponTemplateController         : 接口被fallback 
2024-01-10 14:01:47.813  INFO 13112 --- [o-20006-exec-10] d.daddy.sentinel.SentinelOriginParser    : request org.apache.catalina.util.ParameterMap@39d7b9e0, header=org.apache.tomcat.util.http.NamesEnumerator@7d50964c
2024-01-10 14:01:47.814  INFO 13112 --- [o-20006-exec-10] d.d.s.c.CouponTemplateController         : 接口被fallback
2024-01-10 14:01:47.815  INFO 13112 --- [io-20006-exec-9] d.daddy.sentinel.SentinelOriginParser    : request org.apache.catalina.util.ParameterMap@39d7b9e0, header=org.apache.tomcat.util.http.NamesEnumerator@1f47105b
2024-01-10 14:01:47.816  INFO 13112 --- [io-20006-exec-9] d.d.s.c.CouponTemplateController         : 接口被fallback
...

可以看到降级后,满足条件就会进入熔断。一段时间后会尝试恢复,这个状态叫做半熔断,完整的状态转换参考下图:
在这里插入图片描述

写在后面

参考文章列表

jmeter之简单使用 。

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

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

相关文章

【C#】用CefSharp.ChromiumWebBrowser做winform开发过程中遇到的一些坑

文章目录 使用键盘F5刷新、F12打开控制台浏览器默认下载弹窗禁用GPU配置 使用键盘F5刷新、F12打开控制台 public class CEFKeyBoardHander : IKeyboardHandler {public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int…

【3D动画】Animcraft 基础运用

骨骼包地址&#xff1a;G:\Animcraft相关资料\motion_2024 入库&#xff1a;FBX文件 Mixamo 下载一个模型。格式&#xff1a;FBX 导入到animcraft软件中。

论文封面表格制作

原文参考&#xff1a;【【论文排版】论文封面完美对齐 强迫症重度患者的经验分享】https://www.bilibili.com/video/BV18f4y1p7hc?vd_source046491acdcff4b39fed20406b36a93e2 视频里up主介绍很详细。我自己也记录一下。 介绍一下如何完成论文封面信息的填写。 创建一个3列…

MATLAB对数据隔位抽取和插值的几种方法

对于串行的数据&#xff0c;有时我们需要转成多路并行的数据进行处理&#xff0c;抽取&#xff1b;或者是需要对数据进行隔点抽取&#xff0c;或对数据进行插值处理。此处以4倍抽取或插值为例&#xff0c;MATLAB代码实现。 文章目录 抽取方法一&#xff1a;downsample函数方法…

vue:如果.vue文件内容过多,我们可以这样拆分

一、标签内容太多&#xff0c;我们可以用组件的方式拆分 二、那如果JS的内容太多呢&#xff1f;因为耦合性太高&#xff0c;拆成组件后父子组件传值不方便&#xff0c;我们可以这样&#xff1a; 子组件: export default {data() {return {};},methods: {a(){alert(1)}} };父组…

算法练习:找出数组大于 n/2 的元素

题目&#xff1a; 给定一个大小为 n 的数组nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 n/2 的元素。你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例&#xff1a; 输入&#xff1a;nums [3,2,3] 输出&#xff1a;…

[足式机器人]Part2 Dr. CAN学习笔记 - Ch02动态系统建模与分析

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - Ch02动态系统建模与分析 1. 课程介绍2. 电路系统建模、基尔霍夫定律3. 流体系统建模4. 拉普拉斯变换&#xff08;Laplace&#xff09;传递函数、微分方程4.1 Laplace Transform 拉式变换4.2 收…

Exception sending a multicast message:Network is unreachable故障

出现这个故障就是没有连接到网络&#xff0c;如果虚拟机没有连接到本机&#xff0c;那么就会出现这个情况&#xff0c;当虚拟机连接到本机就会自动消失&#xff0c;同时如果是用电脑直接安装Ubuntu运行也会出现这个情况&#xff0c;应该是要连接到一个路由器里面这个情况才会消…

Python 借助装饰器,实现父对象使用子对象的方法!

文章目录 1. 引言2. 实践2.1 装饰器说明2.2 定义一个父类2.3 定义子类 3. 整体来看4. 参考 1. 引言 这个需求的背景是这样的&#xff0c;我们在写复杂代码时候&#xff0c;可能会用到 Python 的类继承的方法&#xff0c;即子对象继承父对象的一些属性方法。 在这个过程中&…

游戏后端如何实现服务器之间的负载均衡?

网络游戏已成为人们休闲娱乐的重要方式之一。而在游戏开发中&#xff0c;如何实现服务器之间的负载均衡是一个非常关键的问题。负载均衡不仅可以提高服务器的处理能力&#xff0c;还能保证游戏的稳定性和流畅性。本文将探讨游戏后端如何实现服务器之间的负载均衡。 一、负载均…

Eigen 中的传播计算

Eigen: Reductions, visitors and broadcasting

太实用了!关于ControlNet,这篇你一定要看

一篇文章教会你&#xff0c;从入门到使用。 这里是行者AI&#xff0c;我们专注于人工智能在游戏领域的研究和应用&#xff0c;凭借自研算法&#xff0c;推出游戏AI、智能内容审核、数据平台等产品服务。 controlNet控制生成 anypaint 看到这篇文章的你&#xff0c;一定也是AI绘…

SpringBoot整合人大金仓数据库KingBase

1 去KingBase官网下载驱动jar包 2 将解压得到的所有jar包放置在libs目录下&#xff08;没有就新建一个目录&#xff09; 3 在pom文件添加相关依赖 <!--添加KingBase所需要的依赖--> <dependency><groupId>com.kingbase</groupId><artifactId>kin…

DNS解析原理和k8s DNS 实践

1. 问题背景 1.1 域名解析异常 近期开发的一个功能&#xff0c;需要在k8s集群容器环境中调用公司内部api&#xff0c;api提供了内网域名&#xff0c;解析内网域名异常导致请求超时&#xff0c;因此梳理了下DNS的知识点。 可以先看到下面&#x1f447;这段配置&#xff0c;修…

向量数据库:Milvus

特性 Milvus由Go(63.4%),Python(17.0%),C(16.6%),Shell(1.3%)等语言开发开发&#xff0c;支持python&#xff0c;go&#xff0c;java接口(C,Rust,c#等语言还在开发中)&#xff0c;支持单机、集群部署&#xff0c;支持CPU、GPU运算。Milvus 中的所有搜索和查询操作都在内存中执行…

《每天十分钟》-红宝书第4版-基本引用类型

引用值&#xff08;或者对象&#xff09;是某个特定引用类型的实例。在 ECMAScript 中&#xff0c;引用类型是把数据和功能组织到一起的结构&#xff0c;经常被人错误地称作“类”。虽然从技术上JavaScript 是一门面向对象语言&#xff0c;但ECMAScript 缺少传统的面向对象编程…

Disruptor相关问题及答案(2024)

1、Disruptor 是什么&#xff0c;它解决了什么问题&#xff1f; Disruptor是一个高性能的内存中数据交换框架&#xff0c;由LMAX(伦敦多资产交易所)开发&#xff0c;目的是用于支持交易系统中极高的并发处理。它可以说是一个用于线程间消息传递的工具&#xff0c;但与传统的队…

第32次CCF计算机软件能力认证-第一题

仓库规划 问题描述 西西艾弗岛上共有 n个仓库&#xff0c;依次编号为 1…n。每个仓库均有一个m维向量的位置编码&#xff0c;用来表示仓库间的物流运转关系。 具体来说&#xff0c;每个仓库 i均可能有一个上级仓库 j&#xff0c;满足&#xff1a;仓库 j 位置编码的每一维均大…

【XR806开发板试用】XR806无线OTA功能实验

前言 非常感谢基于安谋科技STAR-MC1的全志XR806 Wi-FiBLE开源鸿蒙开发板试用活动,并获得开发板试用。 XR806不仅硬件功能多&#xff0c;XR806也提供了功能极其丰富的SDK&#xff0c;几天体验下来非常容易上手。常见的功能几乎都有相应的cmd或demo实现&#xff0c;HAL也做得非…

Apache ActiveMQ RCE漏洞复现

Apache ActiveMQ RCE漏洞复现&#xff08;CNVD-2023-69477&#xff09; 1、漏洞版本 Apache ActiveMQ < 5.18.3 Apache ActiveMQ < 5.17.6 Apache ActiveMQ < 5.16.7 Apache ActiveMQ < 5.15.16 2、POC 通过dnslog验证的poc.xml <?xml version"1.…