【开发】微服务整合Sentinel

目录

前言

1W:什么是Sentinel?

2W:为什么使用Sentinel?

3W:如何使用Sentinel?

1. 在pom.xml中导入Sentinel依赖坐标

2. 配置控制台

3.  访问API接口的任意端点

流量控制

1. 簇点链路

2. 快速入门

流控模式

1. 直接模式

2. 关联模式

 3. 链路模式

4. 总结

流控效果

1. warm up

2. 排队等待

3. 总结

热点数据限流

1. 标记资源

隔离和降级

FeignClient整合Sentinel

1.修改配置,开启sentinel功能

2. 编写失败降级逻辑

方式①

方法②

3.线程隔离(舱壁模式)

总结


前言

在整合Sentinel前,我们需要了解一下微服务中的雪崩问题:

雪崩问题:在微服务中,如果服务提供者发生了故障,当前应用的部分业务因为依赖于该服务,因此也会被阻塞。请求一直阻塞,会导致服务器资源耗尽,从而导致其他服务都不可用,形成级联失败,从而形成雪崩问题。

1W:什么是Sentinel

  • Sentinel是阿里巴巴开源的一款微服务流量控制组件。

Sentinel官网icon-default.png?t=N7T8https://sentinelguard.io/zh-cn/index.html

2W:为什么使用Sentinel?

  • 丰富的应用场景:Sentinel承接了阿里巴巴近10年来的双十一大促流量的核心场景,例如秒杀(突发流量控制在系统容量的可承受范围内)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel提供实时监控功能。可以在控制台中看到接入到应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的整合模块,例如与Spring CloudDubbogRPC的整合。我们只需要引入相关的依赖并进行简单的配置即可快速地接入Sentinel
  • 完善的SPI扩展点:Sentinel提供简单易用、完善的SPI扩展接口。我们可以通过实现扩展接口来快速地定制逻辑。例如:定制规则管理、适配动态数据源等

3W:如何使用Sentinel?

1. 在pom.xml中导入Sentinel依赖坐标

<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2021.1</version>
</dependency>

2. 配置控制台

 修改application.yaml文件,添加下面内容:

spring:cloud:sentinel:transport:dashboard: localhost:[端口号]

3.  访问API接口的任意端点

打开浏览器,访问http://localhost:端口号/API接口,触发sentinel的监控。

然后访问sentinel控制台

默认路径为:http://localhost:8080页面

默认登录账号:sentinel

默认登录密码:sentinel


流量控制

限流是避免服务因突发的流量而发生故障。

1. 簇点链路

当请求进入微服务时,会首先访问DispatcherServlet,然后进入ControllerServiceMapper,这样的一个调用链叫做簇点链路。

簇点链路中被监控的每一个接口都是一个资源。

默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint,也就是controller层中的方法),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源。

流控、熔断等都是针对簇点链路中的资源来设置,因此我们可以点击对应资源后面的按钮来设置规则:

  • 流控:流量控制
  • 降级:降级熔断
  • 热点:热点参数限流,限流的一种方式
  • 授权:请求的权限控制

2. 快速入门

点击资源/order/prod/{pid}后面的流控按钮,弹出表单。

QPS:线程数(用户数量)/用户访问时间 =请求数/秒,即每秒的响应请求数,也就是最大吞吐量。

  1. sentinel控制台添加限流规则,QPS的单机阈值为五,然后测试。
  2. 利用jmeter测试;

20个用户,2秒内运行完,QPS是10,超过了5

选中流控入门,QPS<5 右击运行:

 结果:成功的请求每次只有5个


流控模式

在添加限流规则时,点击高级选项,可以选择三种流控模式:

  • 直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认模式;
  • 关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流;
  • 链路:统计从指定链路访问到本资源的请求时,触发阈值时,对指定链路限流;

1. 直接模式

 快速入门测试就是直接模式。


2. 关联模式

关联模式:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流;

配置规则:

语法说明:/write资源访问量触发阈值时,就会对/read资源限流,避免影响/write资源

使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是优先支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。

需求说明:

  • 添加两个新的端点:/order/query/order/update
@GetMapping("/order/query")
public String queryOrder(){return "查询订单成功";
}
@GetMapping("/order/update")
public String updateOrder(){return "更新订单成功";
}
  • 配置流控规则,当/order/update资源被访问的QPS超过5时,对/order/query请求限流

可以看到1000个用户,100秒,QPS为10,超过了设置的阈值:5

请求的目标是/order/update,这样这个端点就会触发阈值

但限流的目标是/order/query,我们在浏览器访问,发现:确实被限流了


 3. 链路模式

链路模式:统计从指定链路访问到本资源的请求时,触发阈值时,对指定链路限流;

配置示例:

例如有两条请求链路:

  • /test1 --> /common
  • /test2 --> /common
  • 如果只希望统计从/test2进入到/common的请求,可以这样配置:

需求说明:

1.在OrderService中添加一个queryGoods方法,不用实现业务;

public void queryGoods(){System.err.println("查询商品");
}

2.在OrderController中,改造/order/query端点,调用OrderService中的queryGoods方法;

@GetMapping("/order/query")
public String queryOrder(){//查询商品orderService.queryGoods();//查询订单System.out.println("查询订单");return "查询订单成功";
}

3.在OrderController中添加一个/order/save的端点,调用OrderServicequeryGoods方法

@GetMapping("/order/save")
public String saveOrder(){//查询商品orderService.queryGoods();//查询订单System.out.println("新增订单");return "新增订单成功";}

4.给queryGoods配置限流规则,从/order/query进入queryGoods的方法限制QPS必须小于2

@SentinelResource("goods")
public void queryGoods(){System.err.println("查询商品");
}

链路模式中,是对不同来源的两个链路做监控。但是sentinel默认会给进入Spring MVC的所有请求设置同一个root资源,导致链路模式失效。

我们需要关闭这种对Spring MVC的资源聚合,修改order-service服务的application.yml文件:

spring:cloud:sentinel:web-context-unify: false #关闭context整合

重启服务,访问/order/query/order/save,可以查看sentinel的簇点链路规则中,出现了新的资源:

添加流控规则

点击goods资源后面的流控按钮,在弹出的表单中填写下面信息:

 只统计从/order/query进入/goods的资源,QPS的阈值为2,超出则被限流。

可以看到这里200个用户,50秒内发完,QPS为4,超过了我们设定的阈值2

一个http请求是访问/order/save:运行的结果:完全不受影响


4. 总结

流控模式有哪些?

  • 直接:对当前资源限流;
  • 关联:高优先级资源触发阈值,对低优先级资源限流;
  • 链路:阈值统计时,只统计从指定资源进入当前资源的请求,是对请求来源的限流;

流控效果

流控效果是指请求达到流控阈值时应该采取的措施:

  • 快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式;
  • warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值;
  • 排队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长;

1. warm up

warm up也叫预热模式,是应对服务冷启动的一种方案。请求阈值初始值是maxThreshold / coldFactor,持续指定时长后,逐渐提高到maxThreshold值。而coldFactor的默认值是3;

需求说明:

给/order/prod/{pid}这个资源设置限流,最大QPS为10,利用warm up效果,预热时长为5秒

 刚刚启动时,大部分请求失败,成功的只有3个,说明QPS被限定在3:随着时间推移,成功比例越来越高;


2. 排队等待

当请求超过QPS阈值时,快速失败和warm up会拒绝新的请求并抛出异常。

排队等待是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后面的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。

需求说明:

/order/prod/{pid}这个资源设置限流,最大QPS为10,利用排队的流控效果,超时时长设置为5s

QPS为15,已经超过了我们设定的10

如果是之前的 快速失败、warmup模式,超出的请求应该会直接报错

 全部通过

 QPS非常平滑,一致保持在10,但超出的请求没有被拒绝,而是放入队列。


3. 总结

流控效果:

  • 快速失败:QPS超出阈值时,拒绝新的请求;
  • warm up:QPS超出阈值时,拒绝新的请求;QPS阈值是逐渐提升,可以避免冷启动时高并发导致服务器宕机;
  • 排队等待:请求会进入队列,按照阈值允许的时间间隔依次执行请求;如果请求预期等待时长大于超时时间,直接拒绝;

热点数据限流

分别统计参数值相同的请求,判断是否超过QPS阈值。

案例需求:给/order/prod/{pid}这个资源加热点参数限流,规则如下:

  • 默认的热点参数规则是每1秒请求量不超过2;
  • 给1这个参数设置例外:每1秒请求量不超过4;
  • 给19这个参数设置例外:每1秒请求量不超过10;

注:热点参数限流对默认的Spring MVC资源无效,需要利用@SentinelResouce注解标记资源

1. 标记资源

shop-order中的OrderController中的/order/prod/{pid}资源添加注解:

@SentinelResouce("hot")

访问该接口,可以看到我们标记的hot资源出现了:这里不要点击hot后面的按钮,页面有bug

点击左侧菜单中热点规则菜单:

Jmeter测试

这里发起请求的QPS为5,包含3个http请求:

普通参数,QPS阈值为2

运行结果:每次成功2个请求

例外项,QPS阈值为4

运行结果:每次成功4个请求

例外项,QPS阈值为10

运行结果:每次成功所有请求


隔离和降级

线程隔离:调用者在调用服务提供者时,给每个调用的请求分配独立线程池,出现故障时,最多消耗这个线程池内资源,避免把调用者的所有资源耗尽

熔断降级:调用方这边加入断路器,统计对服务提供者的调用,如果调用的失败比例过高,则熔断该业务,不允许访问该服务的提供者

不管是线程隔离还是熔断降级都是对客户端的保护

FeignClient整合Sentinel

SpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合FeignSentinel

1.修改配置,开启sentinel功能

修改shop-Orderapplication.yml文件,开启FeignSentinel

feign:sentinel:enabled: true # 开启feign对sentinel的支持
2. 编写失败降级逻辑

业务失败后,不能直接报错,而应该返回用户一个友好提示或者默认结果,这个就是失败降级逻辑

给FeignClient编写失败后的降级逻辑

方式一:FallbackClass,无法对远程调用的异常做处理

方法二:FallbackFactory,可以对远程调用的异常做处理

  • 方式①

步骤一:配置yml文件开启支持

feign:sentinel:enabled: true

步骤二:创建ProductServiceFallBack类实现降级方案编辑

@Component
public class ProductServiceFallBack implements IProductService{@Overridepublic Product findByPid(Integer pid){Product product = new Product();product.setPid(-1);product.setPname("暂无商品");return product;}}

步骤三:配置属性

@FeignClent(value="service-product",fallbackFactory = ProductServiceFallBack.class)
  • 方法②

步骤一:配置yml文件开启支持

feign:sentinel:enabled: true

 步骤二:创建ProductServiceFallBack类实现降级方案编辑

@Component
public class ProductServiceFallBack implements FallBackFactory<ProductService>{@Overridepublic ProductService create(Throwable throwable){return new ProductService(){@Overridepublic Product findByPid(Integer pid){System.out.println("异常信息:"+throwable);Product product = new Product();product.setPid(-1);product.setPname("暂无商品");return product;        }};}
}

步骤三:配置属性

@FeignClient(value="service-product",fallbackFactory = ProductServiceFallBack.class)
3.线程隔离(舱壁模式)
  • 线程池隔离:给每个服务调用业务分配一个线程池,利用线程池本身实现隔离效果
  • 信号量隔离(Sentinel默认采用):不创建线程池,而是计数器模式,记录业务使用的线程数量,达到信号量上限时,禁止新的请求

案例需求:给order-service服务中的UserClient的查询用户接口设置流控规则,线程数不能超过2然后利用Jmeter测试。

一次发送10个请求,有较大概率并发线程数超过2,而超出的请求会走之前定义的失败降级逻辑。

发现虽然结果是通过了,不过部分请求得到的响应是降级返回的null信息。


总结

线程隔离的两种手段是

  • 信号量隔离
  • 线程池隔离

信号量隔离的特点:

  • 基于计数器模式,简单,开销小

线程池隔离的特点:

  • 基于线程池模式,有额外开销,但隔离控制更强

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

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

相关文章

PCM和I2S区别

I2S和PCM接口都是数字音频接口&#xff0c;而所见的蓝牙到cpu以及codec的音频接口都是用PCM接口&#xff0c;是不是两个接口有各自不同的应用呢&#xff1f;先来看下概念。 PCM&#xff08;PCM-clock、PCM-sync、PCM-in、PCM-out&#xff09;脉冲编码调制&#xff0c;模拟语音信…

Unity WebGL服务器标头的问题

目录 现象&#xff1a; 报错文本: 原因: 解决方案: 现象&#xff1a; 打包前&#xff0c;ProjectSetting 压缩选项设置为Brotli, 将打包的WebGL部署到阿里云OSS环境后&#xff0c;运行弹框提示错误. 报错文本: Unable to parse Build/WebGL.framework.js.br! This canha…

Elasticsearch 索引库操作 文档操作

索引库就类似数据库表&#xff0c;mapping映射就类似表的结构。要向es中存储数据&#xff0c;必须先创建“库”和“表”。 mapping映射属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; type&#xff1a; 字段数据类型&#xff0c;常见的简…

记一些有关Element Plus的样式修改

先记一个放着&#xff0c;后续慢慢补充。。。 一个 Vue 3 UI 框架 | Element Plus Radio 单选框 1、去除radio的圆圈 .box-radio {/deep/ .el-radio__input {display: none;} }

LLM之RAG实战(二十九)| 探索RAG PDF解析

对于RAG来说&#xff0c;从文档中提取信息是一种不可避免的场景&#xff0c;确保从源文件中提取出有效的内容对于提高最终输出的质量至关重要。 文件解析过程在RAG中的位置如图1所示&#xff1a; 在实际工作中&#xff0c;非结构化数据比结构化数据丰富得多。如果这些海量数据无…

unity3d Animal Controller的Animal组件中Stances,Advanced基础部分理解

Stances 立场 立场要求在动物动画控制器上的姿态动画参数。 你可以有多个运动状态,并根据当前的立场使用它们 过渡的条件是: Stance StanceID Default Stance默认姿势 如果调用函数Stance_Reset&#xff08;&#xff09;&#xff0c;动物将返回到的默认姿势。 Current …

如何使用ArcGIS Pro生成带计曲线等高线

等高线作为常见的地图要素经常会被使用到&#xff0c;一般情况下生成的等高线是不带计曲线的&#xff0c;在某些情况下我们需要带计曲线的等高线&#xff0c;这里为大家介绍一下ArcGIS Pro生成带计曲线等高线的方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数…

upload-labs第一关

上一篇文章中搭建好了upload-labs环境&#xff0c;接下来进行第一关的尝试&#xff0c;我也是第一次玩这个挺有意思。 1、第一关的界面是这样的先不看其他的源码&#xff0c;手动尝试下试试。 2、写一个简单的php一句话木马 3、直接上传&#xff0c;提示必须要照片格式的文…

数字后端 EDA 软件分享

数字后端 EDA 软件分享 推荐这几家的EDA工具吧&#xff0c;虽说我也支持国产工具&#xff0c;但是我还是选择了这几家的工具 apache cadence mentor synopsys 下图我现在用的eda环境&#xff0c;利用网上的资源&#xff0c;自己独立在vmware上搭建好的EDA环境 除去pdk&#…

Linux基础开发工具之yum与vim

1. Linux软件包管理器——yum 1.1 什么是软件包&#xff1f; 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, …

海外媒体宣发套餐推广攻略实现品牌全球化-华媒舍

如今&#xff0c;在全球经济一体化的浪潮下&#xff0c;品牌全球化已成为企业成功的重要因素之一。海外市场作为一个巨大而具有潜力的机会&#xff0c;吸引着越来越多的企业前往探索。而在海外市场的推广过程中&#xff0c;海外媒体宣发套餐成为了重要的推广方式之一。本文将为…

设计模式在芯片验证中的应用——装饰器

一、装饰器模式 装饰器模式(Decorator)是一种结构化软件设计模式&#xff0c;它提供了一种通过向类对象添加行为来修改类对象的方法&#xff0c;而不会影响同一类的其它对象行为。该模式允许在不修改抽象类的情况下添加类功能。它从本质上允许基类代码对不可预见的修改具有前瞻…

解决Linux中Eclipse启动时找不到Java环境的问题

按照报错的意思是没有在/usr/local/eclipse/jre/bin/java下找到java环境&#xff0c;我检查了一下eclipse的目录结构发现在/usr/local/eclipse没有jre/bin/java&#xff0c;我的想法是自己建对应文件夹然后软连接到我的java环境 cd /usr/local/eclipse sudo mkdir jre cd jre s…

python实现--二叉搜索树

什么是二叉搜索树 二叉搜索树&#xff08;Binary Search Tree&#xff0c;BST&#xff09;是一种特殊类型的二叉树&#xff0c;它具有以下性质&#xff1a; 每个节点最多有两个子节点&#xff0c;分别称为左子节点和右子节点。 对于任意节点&#xff0c;其左子树中的所有节点的…

jwt以及加密完善博客系统

目录 一、背景 二、传统登陆功能&强制登陆功能 1、传统的实现方式 2、session存在的问题 三、jwt--令牌技术 1、实现过程 2、令牌内容 3、生成令牌 4、检验令牌 四、JWT登陆功能&强制登陆功能 1、JWT实现登陆功能 2、强制登陆功能 3、运行效果 五、加密/加…

C++之多态

目录 1、为什么要用多态&#xff1f; 2、虚函数的定义 3、虚函数的实现机制 4、哪些函数不能被设置为虚函数&#xff1f; 5、虚函数的访问 5.1、指针访问 5.2、引用访问 5.3、对象访问 5.4、成员函数中访问 5.5、构造函数和析构函数中访问 6、纯虚函数 7、抽象类 …

串变换dfs

分析&#xff1a; DFS,注意判断是否遍历结束&#xff0c;返回false 代码示例&#xff1a; #include<bits/stdc.h> using namespace std; int n,k; string s,t; struct {int op;int x;int y; }cha[10]; int vis[10]; bool dfs(int dep){if(st)return true;if(depk1)retu…

Qt教程 — 3.3 深入了解Qt 控件:Input Widgets部件(2)

目录 1 Input Widgets简介 2 如何使用Input Widgets部件 2.1 QSpinBox组件-窗口背景不透明调节器 2.2 DoubleSpinBox 组件-来调节程序窗口的整体大小 2.3 QTimeEdit、QDateEdit、QDateTimeEdit组件-编辑日期和时间的小部件 Input Widgets部件部件较多&#xff0c;将分为三…

滑动窗口最大值(leetcode hot100)

给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a;nums [1,3,-1,-3,5,3,6,7], k 3 输…

C++:菱形继承与虚继承

看下面这个示例代码 class A{ public: int num10; A(){cout<<"A构造"<<endl;} virtual void fun(){cout<<"A虚函数"<<endl;} };class B:public A{ public: B(){cout<<"B构造"<<endl;} void fun(){cout<…