😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!

文章目录
预谋学习springcloud-alibaba组件这么久,由于自身以及工作的原因脱了这么久,近期就开始逐步恢复学习,学完了nacos组件、openfeign组件以及负载均衡,接下来就是对流量控制的学习sentinel组件。
学习sentinel首先要知道什么是服务雪崩与容错机制,最后再来通过集成Sentinel来提供服务治理和容错的能力。
服务雪崩就是当一个或多个服务出现故障或不可用时,这些故障会导致其他服务也因为等待或依赖这些服务而崩溃,最终整个系统不可用的情况。服务雪崩通常发生在高并发的情况下,当请求量增加时,一些服务可能会因为超负荷而变得不稳定或不可用,导致其他服务也因此被阻塞或超时,从而使整个系统出现连锁反应,最终导致系统崩溃。

导致雪崩的原因有许多
当大量得请求造成了请求失败,会不断得重试,这反而还会加重请求流量,造成雪崩效应。归根到底也就是大量得线程同步等待造成的资源耗尽。
容错机制是指在分布式系统中,通过设计和实现一些技术手段和策略,使系统能够在出现故障、错误或异常的情况下仍然能够继续运行,保证系统的可用性和可靠性。
当服务达到一定的临界值的时候,有可能会导致服务宕机。常见使用的是服务限流,首先会对服务进行压测,测出最大的QPS(每秒处理的请求数量),当开启限流时,大于规定限流的QPS就会被限流,对于这些限流的请求,可以是进行流量降级,或者是直接拒绝。
超时机制就是当大量的请求得不到相应会线程等待,如果检测到超时,就会释放资源。
当服务不稳定或者暂时关闭,这就是服务熔断。在现实中,这就好比如空气开关在电路出现过载、短路等故障时,及时切断电路,以保护电气设备和人身安全,防止电路烧坏。而在软件上,服务熔断的实现原理通常是通过对服务请求进行监控,当服务请求的失败率达到一定的阈值时,服务熔断器会自动打开,将后续请求快速失败返回,而不是一直等待服务超时。当服务熔断器处于打开状态时,一部分请求会快速失败返回,而另一部分请求则会被拦截,从而避免服务雪崩的发生。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调, 返回一个缺省值。 例如:(备用接口/缓存/mock数据) 。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当 然这也要看适合的业务场景。服务降级是通过削减服务的负载或者降低服务的质量来保证系统的稳定性。
Sentinel是一个轻量级的开源框架,它提供了实时监控、流量控制、熔断降级等功能,可以在微服务架构中用于保护服务的稳定性和可靠性。在Spring Cloud中,可以通过集成Sentinel来提供服务治理和容错的能力。

官方网站:https://sentinelguard.io/zh-cn/docs/quick-start.html
功能包括如下:
1.流量控制:通过限流的方式来控制服务的请求量,防止系统超负荷而导致的故障和错误。
2.熔断降级:当服务出现故障或异常时,可以通过熔断机制来控制请求量,保护服务的可用性和稳定性。
3.实时监控:可以通过Dashboard界面来实时监控服务的运行情况,包括流量、响应时间、异常等信息。
4.异常处理:可以通过定义规则来处理各种异常情况,例如超时、限流、熔断等,提高服务的容错能力。
5.集成Spring Cloud:Sentinel可以和Spring Cloud的组件集成,也可以是由springboot集成,例如Eureka、Ribbon、Feign等,方便在微服务架构中使用。
Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。
首先使用核心库的方式。
引入sentinel的核心库依赖
<!-- 整合sentinel-核心库,支持分布式系统,并不一定需要微服务,因此可以不添加springcloud -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version>
</dependency>
根据sentinel官方文档说的来,需要先定义资源,定义规则,接着校验规则是否生效的步骤。
定义资源:
资源 是 Sentinel 中的核心概念之一。在本次demo,定义一个资源名称为:RESOURCE_NAME = “test”,我们需要把需要控制流量的代码用Sentinel API SphU.entry("HelloWorld")和 entry.exit() 包围起来即可。通过SphU.entry(RESOURCE_NAME)来指定流量控制的资源。
Entry entry = null;
try {
// sentinel对指定的资源进行流控
entry = SphU.entry(RESOURCE_NAME); // 配置流控规则
// 业务...
log.info(">>>执行正常业务流程>>>");
return "执行业务";
} catch (BlockException be) {
// 阻止资源访问,被限流或者降级
log.info("block");
return "流量控制";
} catch (Exception ex) {
// 若需要配置降级规则,需要通过这种方式记录业务异常
Tracer.traceEntry(ex, entry);
} finally {
if (entry != null) {
entry.exit();
}
}
return null;
定义规则:
通过initFlowRules方法来定义规则,因为流控规则可以有多个,因此使用一个流控集合,FlowRule就是流控规则。可以设置需要控制的资源以及流控规则(本次设置的是QPS),定义完规则之后,在通过FlowRuleManager.loadRules方法加载规则。
从官网中可以知道流量控制规则可以设置的参数如下:

/**
* 定义规则
*/
@PostConstruct
private static void initFlowRules() {
// 设置流控规则 流控规则可以多个
List<FlowRule> rules = new ArrayList<>();
// 流控规则
FlowRule rule = new FlowRule();
// 设置流控资源
rule.setResource(RESOURCE_NAME);
// 设置流控规则 - QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置阈值
rule.setCount(1);
rules.add(rule);
// 加载配置的规则
FlowRuleManager.loadRules(rules);
}
运行几次之后,可以看到被限流了

由以上例子可以看得出使用Sentinel API SphU.entry("HelloWorld") 和 entry.exit() 包围起来写起来非常麻烦,在实际开发中,用这样写是相当麻烦的。好在sentinel中提供了注解的方式来进行流量控制的使用。
需要添加sentinel-annotation-aspectj的pom依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.6</version>
</dependency>
为了方便使用,就在启动类中配置SentinelResourceAspect
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
前一个demo是通过SphU.entry来配置资源,而现在就只需要添加在注解的value属性上。通过blockHandler设置流控降级的处理方法,需要注意的是注解方式埋点不支持 private 方法,blockHandler指定的方法需要在当前类中来定义,如果在其他类,就需要额外参数**blockHandlerClass = “”**来指明类的地址。这里还有个fallback属性,这是用来指定接口异常执行的方法。
@SentinelResource属性如下
- value:资源名称,必需项(不能为空)
- entryType:entry 类型,可选项(默认为 EntryType.OUT)
- blockHandler/blockHandlerClass :blockHandler 对应处理 BlockException 的函数名称,需要用public修饰,并且参数和返回类型要与原函数相同,需要在同个类中;如果不在同个类,就需要使用blockHandlerClass属性,为对应的类的 Class 对象,注意对应的函数必需为 static 函数
- fallback/ fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。函数的相关条件与blockHandler一样。
- defaultFallback:默认的 fallback 函数名称。
- exceptionsToIgnore:用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
以下代码就是在test2接口中通过添加**@SentinelResource注解进行流量控制。
*** blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,而 fallback 函数会针对所有类型的异常。
/**
* @SentinelResource: 改善接口中资源定义以及流量降级的处理方法
* value: 资源名称
* blockHandler: 流量降级的处理方法(默认处理方法要在同类中)
* 如果不在同个类,就需要额外参数blockHandlerClass = "",来指明类的地址, 并需要用静态方法
* fallback: 用来指定接口异常执行的方法
* @return
*/
@GetMapping("/test2")
(value = RESOURCE_NAME2, blockHandler = "blockHandlerTs")
public String test2(String id) {
log.info("<<<测试2<<<" + id);
return "正常返回";
}
设置流量降级方法的时候,对于参数以及返回类型,都要与控制类相同。
/**
* 一定是public, 返回的类型/与参数要与接口的类型相同
* @param id
* @param ex
* @return
*/
public String blockHandlerTs(String id, BlockException ex) {
ex.printStackTrace();
return "流量控制";
}
接下来就可看看执行的结果,疯狂请求几次。。。

对于熔断降级规则 (DegradeRule)配置如下

同一个资源可以同时有多个降级规则。通过**degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);**设置熔断策略,它是基于异常数量的熔断降级策略,当系统中某个资源的异常数超过设定的阈值后,触发降级策略,进入熔断状态。接着通过 **degradeRule.setStatIntervalMs(60*1000);**设置统计时长1分钟,单位是毫秒,**degradeRule.setTimeWindow(10);**这个是将统计时间窗口设置为60秒,表示每隔60秒对该资源的运行状况进行一次统计和计算。这表示一分钟出现两次异常就会熔断降级。10秒过去之后就会变成:半开状态,恢复请求调用,在十秒过后,如果再一次请求异常,就会再次熔断,不会根据设置的条件进行判断。
/**
* 熔断降级规则
*/
@PostConstruct
private static void initDegradeRules() {
// 降级规则
List<DegradeRule> degradeRules = new ArrayList<>();
DegradeRule degradeRule = new DegradeRule();
// 设置资源
degradeRule.setResource(DEGRADE_NAME);
// 设置熔断策略
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
// 统计时长:单位:ms,这里设置1分钟
degradeRule.setStatIntervalMs(60*1000);
// 一分钟执行两次,出现两次异常就会熔断降级
// 熔断持续时长:单位:秒
// 一旦触发熔断,再次请求对应接口就会调用降级方法
// 10秒过去之后就会变成:半开状态,恢复请求调用,如果第一次请求异常,再次熔断,不会根据设置的条件进行判断
degradeRule.setTimeWindow(10);
degradeRules.add(degradeRule);
DegradeRuleManager.loadRules(degradeRules);
}
到官网下载jar包 https://github.com/alibaba/Sentinel/releases
用命令窗口运行jar包
java -Dserver.port=1111 -Dcsp.sentinel.dashboard.server=localhost:1111 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
启动访问http://localhost:1111/ 就能看到登录界面,账号密码都是sentinel

在springcloud项目中的yml添加配置,需要配置服务名以及sentinel-dashboard的地址
server:
port: 8122
spring:
application:
name: order-sentinel
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:1111
启动项目,访问一个接口,就可以在sentinel控制台看到服务了

sentinel能够很好的对接口请求进行请求控制,能够在一定程度防止服务挂掉,并且不一定是需要依赖spring-cloud。能够通过api的方式以及可视化控制台进行流控、降级管理。
👍创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得点赞哦!👍
虽然在学习之前,有看过几篇博客,当时是为了启动若依的微服务项目,并不是真正会用sentinel,以上介绍如有错误,请各位大佬评论区指出!
我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实
我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id
在Ruby中,以毫秒为单位获取自纪元(1970)以来的当前系统时间的正确方法是什么?我试过了Time.now.to_i,好像不是我想要的结果。我需要结果显示毫秒并且使用long类型,而不是float或double。 最佳答案 (Time.now.to_f*1000).to_iTime.now.to_f显示包含十进制数字的时间。要获得毫秒数,只需将时间乘以1000。 关于ruby-以毫秒为单位获取当前系统时间,我们在StackOverflow上找到一个类似的问题:
我希望访问我机器上的所有HTTP流量(我的Windows机器-不是服务器)。据我了解,拥有一个本地代理是所有流量路线的必经之路。我一直在谷歌搜索但未能找到任何资源(关于Ruby)来帮助我。非常感谢任何提示或链接。 最佳答案 WEBrick中有一个HTTP代理(Rubystdlib的一部分)和here's一个实现示例。如果你喜欢生活在边缘,还有em-proxy伊利亚·格里戈里克。这postIlya暗示它似乎确实需要一些调整来解决您的问题。 关于ruby-如何捕获所有HTTP流量(本地代理)
关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭8年前。Improvethisquestion我们有以下(以及更多)系统,我们将数据从一个应用推送/拉取到另一个:托管CRM(InsideSales.com)Asterisk电话系统(内部)横幅广告系统(openx,我们托管)潜在客户生成系统(自行开发)电子商务商店(spree,我们托管)工作板(本土)一些工作网站抓取+入站工作提要电子邮件传送系统(如Mailchimp,自主开发)事件管理系统(如eventbrite,自主开发)仪表板系统(大量图表和