微服务雪崩防护最佳实践之sentinel

思考

1、当服务访问量达到一定程度,流量扛不住的时候,该如何处理?

2、服务之间相互依赖,当服务A出现响应时间过长,影响到服务B的响应,进而产生连锁反应,直至影响整个依赖链上的所有服务,该如何处理?

这是分布式、微服务开发不可避免的问题。

我们系统假如是这样的调用图。当G服务出现程序Bug,大流量请求,硬件故障,缓存击穿时,导致服务不可用。进而导致D服务不可用,导致A服务不可用。

B、C、D三个服务共享A服务的线程池,当D服务出现故障时,则导致A服务中所有线程池都在等待D服务响应而被阻塞。进而导致A服务不可用

 解决方案

超时机制

在不做任何处理的情况下,服务提供者不可用会导致消费者请求线程强制等待,而造成系统资源耗尽。加入超时机制,一旦超时,就释放资源。由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。

服务限流(资源隔离)

限制请求核心服务提供者的流量,使大流量拦截在核心服务之外,这样可以更好的保证核心服务提供者不出问题,对于一些出问题的服务可以限制流量访问,只分配固定线程资源访问,这样能使整体的资源不至于被出问题的服务耗尽,进而整个系统雪崩。那么服务之间怎么限流,怎么资源隔离?例如可以通过线程池+队列的方式,通过信号量的方式。

当D服务出问题时,A调用C服务和B服务不受影响。

服务熔断

远程服务不稳定或网络抖动时暂时关闭,就叫服务熔断。

服务降级

有服务熔断,必然要有服务降级。

sentinel开源功能不足之点

 相信用过开源版本sentinel的小伙伴,会发现当服务重新启动是,sentinel控制台规则数据则失效;接下里引入sentinel-datasource-nacos 规则持久化,来解决sentinel规则失效问题。但是发现在sentinel的dashboard的客户端更改规则生效,但是nacos中的配置未发生变更,导致dashboard的和nacos的数据不一致现象。

 

红色的箭头未实现,就会导致dashboard配置的规则和nacos配置中的数据不一致。

为了解决这个问题,官方的建议是在dashboard源码中进行改造,直接写入数据到nacos中。标红的部分

所以实现dashboard和nacos中的数据规则一致,则有两个方案:

 方案一 需要在应用服务端进行改造

方案二 需要在dashboard的源码中进行改造(官方推荐

设计模式的核心理念逻辑之一:开放封闭原则。选择方案一比较好点。

我对方案一进行的实现。

代码实现

1.SpringContextHolder 工具类(为了能获取到配置中变量)

@Component
public class SpringContextHolder implements ApplicationContextAware {private static ApplicationContext context;public static ApplicationContext getContext() {return context;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {context = applicationContext;}
}

2. SentinelNacosProperties 实体类

public class SentinelNacosProperties {public String serverAddr;public String groupId;public String dataId;public String username;public String password;public String namespace;public String appName;
//自己添加get/set方法
}

 3.利用sentinel的扩展点InitFunc(NacosDataSourceInitFunc)

@Slf4j
public class NacosDataSourceInitFunc implements InitFunc {@Overridepublic void init() throws Exception {log.info("NacosDataSourceInitFunc init...");Environment env = SpringContextHolder.getContext().getEnvironment();String appName = env.getProperty("spring.application.name", "demo-project");String groupId = "SENTINEL_GROUP";String serverAddr = env.getProperty("spring.cloud.nacos.config.server-addr", "localhost:8848");String namespace = env.getProperty("spring.cloud.nacos.config.namespace", "public");String username = env.getProperty("spring.cloud.nacos.config.username", "nacos");String password = env.getProperty("spring.cloud.nacos.config.password", "xx#pj70Qdd1");log.info("NacosDataSourceInitFunc appName:{}, group:{}, serverAddr:{}", appName, groupId, serverAddr);SentinelNacosProperties sentinelNacosProperties = new SentinelNacosProperties();sentinelNacosProperties.setAppName(appName);sentinelNacosProperties.setGroupId(groupId);sentinelNacosProperties.setServerAddr(serverAddr);sentinelNacosProperties.setNamespace(namespace);sentinelNacosProperties.setUsername(username);sentinelNacosProperties.setPassword(password);// =============== FlowRule 流控规则 ==================String flowDataId = appName + "-flow-rules";sentinelNacosProperties.setDataId(flowDataId);WritableDataSource<List<FlowRule>> flowRuleWritableDataSource = new NacosWritableDataSource<>(sentinelNacosProperties, JSON::toJSONString);WritableDataSourceRegistry.registerFlowDataSource(flowRuleWritableDataSource);// =============== DegradeRule 降级规则 ==================String degradeDataId = appName + "-degrade-rules";sentinelNacosProperties.setDataId(degradeDataId);WritableDataSource<List<DegradeRule>> degradeRuleWritableDataSource = new NacosWritableDataSource<>(sentinelNacosProperties, JSON::toJSONString);WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWritableDataSource);// =============== AuthorityRule 授权规则 ==================String authorityDataId = appName + "-authority-rules";sentinelNacosProperties.setDataId(authorityDataId);WritableDataSource<List<AuthorityRule>> authorityRuleWritableDataSource = new NacosWritableDataSource<>(sentinelNacosProperties, JSON::toJSONString);WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWritableDataSource);// =============== SystemRule 系统规则 ==================String systemDataId = appName + "-system-rules";sentinelNacosProperties.setDataId(systemDataId);WritableDataSource<List<SystemRule>> systemRuleWritableDataSource = new NacosWritableDataSource<>(sentinelNacosProperties, JSON::toJSONString);WritableDataSourceRegistry.registerSystemDataSource(systemRuleWritableDataSource);log.info("NacosDataSourceInitFunc init finished");}
}

由于sentinel的各个规则都可以在不同的nacos服务上,根据自己的修改此配置。

4. 写数据源的实现

import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Value;import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** Sentinel nacos写数据源实现**/
public class NacosWritableDataSource<T> implements WritableDataSource<T> {private final String serverAddr;private final String groupId;private final String dataId;private final String username;private final String password;private final String namespace;private final Properties properties;private ConfigService configService;private final Converter<T, String> configEncoder;private final Lock lock = new ReentrantLock(true);public NacosWritableDataSource(SentinelNacosProperties nacosProperties, Converter<T, String> configEncoder) {this.serverAddr = nacosProperties.getServerAddr();this.namespace = nacosProperties.getNamespace();this.groupId = nacosProperties.getGroupId();this.dataId = nacosProperties.getDataId();this.username = nacosProperties.getUsername();this.password = nacosProperties.getPassword();this.properties = NacosWritableDataSource.buildProperties( nacosProperties);this.configEncoder = configEncoder;initConfigService();}private void initConfigService() {try {this.configService = NacosFactory.createConfigService(properties);} catch (NacosException e) {e.printStackTrace();}}private static Properties buildProperties(SentinelNacosProperties nacosProperties) {Properties properties = new Properties();properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosProperties.getServerAddr());properties.setProperty(PropertyKeyConst.NAMESPACE, nacosProperties.getNamespace());properties.setProperty(PropertyKeyConst.USERNAME, nacosProperties.getUsername());properties.setProperty(PropertyKeyConst.PASSWORD, nacosProperties.getPassword());return properties;}@Overridepublic void write(T t) throws Exception {lock.lock();try {configService.publishConfig(dataId, groupId, this.configEncoder.convert(t));} finally {lock.unlock();}}@Overridepublic void close() throws Exception {}}

5. application.yml 规则定义

spring:cloud:sentinel:transport:dashboard: localhost:8080 # Sentinel 控制台地址port: 8719 # 本地启动的端口,用于与 Sentinel 控制台通信eager: true # 是否立即初始化web-context-unify: false # 是否合并 Web 上下文datasource:flow-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-flow-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: flowdegrade-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-degrade-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: degradeparam-flow-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-param-flow-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: param-flowauthority-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-authority-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: authoritysystem-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-system-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: system

nacos的配置自己添加一下即可。

5.由于我们利用的sentinel的SPI机制

需要以下的文件夹META-INF/services/

com.alibaba.csp.sentinel.init.InitExecutor的类

 将你的实现类按照图中存放即可。

 测试

nacos中流控规则中的阈值是33.

dashboard的界面显示也是33.则代表nacos->服务内存->dashboard 这条链路已经走通。 

 现在我们在dashboard上进行修改阈值为:55

查看naocs是否同步修改:

 

nacos中已经修改,则代表方案一已实现。

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

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

相关文章

阿里云监控及运维常见问题

云监控介绍&#xff1a;阿里云的云监控服务&#xff08;CloudMonitor&#xff09;是一款简单易用、功能强大的监控工具&#xff0c;主要用来帮助用户实时监控阿里 云上的各种资源&#xff08;比如服务器、数据库、网络等&#xff09;&#xff0c;并在出现问题时及时发出警报&am…

深入解析 vLLM 分布式推理与部署策略

在当今人工智能快速发展的时代&#xff0c;大型语言模型&#xff08;LLM&#xff09;的推理和部署面临着诸多挑战&#xff0c;尤其是当模型规模日益庞大时&#xff0c;如何高效地利用硬件资源成为关键问题。vLLM 作为一种强大的工具&#xff0c;为分布式推理和部署提供了多种策…

PostgreSQL 终端命令详解及实际应用案例

PostgreSQL 作为一款功能强大的开源关系型数据库&#xff0c;其终端命令是数据库管理员、开发人员日常操作的核心工具。这些命令覆盖数据库连接、对象管理、数据操作、备份恢复、权限控制等多个维度&#xff0c;掌握其实际应用场景能显著提升工作效率。本文结合不同行业的实操案…

步进电机基础

1、ENABLE‾\overline{ENABLE}ENABLE 的意思&#xff1a; ENABLE上面的横线表示这是一个低电平有效的信号&#xff1a;当ENABLE信号为低电平&#xff08;0V或逻辑0&#xff09;时&#xff0c;芯片被使能&#xff08;激活&#xff09;当ENABLE信号为高电平&#xff08;VDD或逻辑…

Redis进阶--缓存

目录 一、引言 二、介绍 1.为什么Mysql的速度慢呢&#xff1f; 2.缓存更新策略 1.定期生成 2.实时生成 3.redis的内存淘汰机制 4.注意事项 1.缓存预热 2.缓存穿透 3.缓存击穿 4.缓存雪崩 三、总结 一、引言 本篇文章将介绍Redis其中一个重要的作用&#xff0c;作为…

微软原版系统下载的几个好用网站

“不要因为走得太远&#xff0c;而忘记为什么出发。” 愿每一位Windows用户&#xff0c;都能在这份情怀中找到属于自己的小确幸&#xff01;满满的情怀&#xff01; 微软官方渠道 微软官网提供纯净的ISO镜像下载&#xff0c;适用于Windows 10/11等系统。访问Microsoft官网下…

kotlin Flow快速学习2025

其实&#xff0c;第一章节&#xff0c;只是让你了解下Flow的基本情况。我们开发中&#xff0c;基本很少使用这种模式。所以来讲&#xff0c;我们甚至可以直接使用StateFlow和SharedFlow才是正途。这是很多教程没有说明的点。所以第一章随便浏览下即可。日后再补充理解都是可以的…

【人工智能99问】什么是教师强制?(16/99)

文章目录什么是教师强制&#xff1f;教师强制&#xff08;Teacher Forcing&#xff09;的定义原比例&#xff08;Original Proportion&#xff09;教师强制的举例说明&#xff08;一&#xff09;教师强制的举例说明&#xff08;二&#xff09;优点和缺点解决曝光偏差的方法什么…

【WPF】WPF 自定义控件之依赖属性

&#x1f4e6; WPF 自定义控件之依赖属性 在开发 WPF 应用时&#xff0c;自定义控件能帮助我们复用逻辑和样式&#xff0c;但我很快会遇到一个问题&#xff1a;在控件内部如何支持数据绑定和属性变更通知&#xff1f;特别是我们继承自 Control 的时候&#xff0c;已经不能再继承…

DOM型XSS破坏

目录 首先 然后 第一种 第二种&#xff08;DOM&#xff09; HTMLCollection HTML Relationships Custom 解 首先 <script>//urlencode解码 //location接口的hash属性是一个字符串&#xff0c;包含一个“#”后跟位置URL的片段标识符。如果URL没有片段标识符&#…

Linux C 多线程基本操作

我们已经了解进程的基本概念&#xff1a;进程是正在执行的程序&#xff0c;并且是系统资源分配的基本单位。当用户需要在一台计算机上去完成多个独立的工作任务时&#xff0c;可以使用多进程的方式&#xff0c;为每个独立的工作任务分配一个进程。多进程的管理则由操作系统负责…

C语言基础:二维数组练习题

1. 一个二维数组赋了初值&#xff0c;用户输入一个数&#xff0c;在该二维数组中查找。找到则返回行列位置&#xff0c;没找到则提示。#include <stdio.h>int main() {int arr[3][3] {{1, 2, 3},{4, 5, 6},{7, 8, 9}};int t;printf("要查找的数&#xff1a;")…

Java面试题034:一文深入了解MySQL(6)

Java面试题029&#xff1a;一文深入了解MySQL&#xff08;1&#xff09; Java面试题030&#xff1a;一文深入了解MySQL&#xff08;2&#xff09; Java面试题031&#xff1a;一文深入了解MySQL&#xff08;3&#xff09; Java面试题032&#xff1a;一文深入了解MySQL&#x…

Java基础教程(011):面向对象中的构造方法

10-面向对象-构造方法 构造方法也叫做构造器、构造函数。 作用&#xff1a;在创建对象的时候给成员变量进行初始化的。 ✅ 一、构造方法的特点特点说明与类同名构造方法的名称必须与类名相同没有返回类型构造方法没有返回值&#xff0c;甚至不能写 void自动调用使用 new 创建对…

Adobe Photoshop:数字图像处理的终极工具指南

Hi&#xff0c;我是布兰妮甜 &#xff01;Adobe Photoshop自1990年问世以来&#xff0c;已经成为数字图像处理领域的标杆和代名词。这款强大的软件不仅彻底改变了摄影、设计和艺术创作的方式&#xff0c;还深刻影响了我们消费和感知视觉内容的文化方式。从专业摄影师到社交媒体…

本期来讲讲什么是LVS集群?

集群和分布式 集群&#xff08;Cluster&#xff09;&#xff0c;解决某个问题将多台计算机组合形成的系统群。 常见的集群类型&#xff1a; 负载均衡(LoadBalancing&#xff0c;简称LB)&#xff1a;由多个相同配置的主机组成&#xff0c;每个主机经过调度承担部分访问&#…

JVM 类加载过程笔记

一、概述 JVM&#xff08;Java Virtual Machine&#xff09;在运行 Java 程序时&#xff0c;需要将 .class 字节码文件加载到内存中&#xff0c;并转换成可以被 JVM 执行的数据结构&#xff0c;这一过程就是 类加载过程&#xff08;Class Loading Process&#xff09;。 JVM 的…

基于爬虫技术的电影数据可视化系统 Python+Django+Vue.js

本文项目编号 25002 &#xff0c;文末自助获取源码 \color{red}{25002&#xff0c;文末自助获取源码} 25002&#xff0c;文末自助获取源码 目录 一、系统介绍二、系统录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状 六、核心代码6.1 查询数据6.2 新…

如何用 LUKS 和 cryptsetup 为 Linux 配置加密

在信息安全愈发重要的今天&#xff0c;为 Linux 系统盘配置全盘加密已经成为很多企业和个人的选择。LUKS&#xff08;Linux Unified Key Setup&#xff09;配合工具 cryptsetup 可以在不牺牲性能的前提下实现高强度加密。本文将通过一个故事化的场景&#xff0c;介绍整个配置过…

VIVADO技巧_BUFGMUX时序优化

1.版本说明日期作者版本说明2025xxxx风释雪初始版本 2.概述 基于VIVADO时序约束&#xff0c;BUFGMUX多路时钟选择原语的设计3.原语介绍 7系列FPGA/UltraSCale/UltraSCaleBUFGMUX_CTRL BUFGMUX_CTRL_inst (.O(O), // 1-bit output: Clock output.I0(I0), // 1-bit input: Cloc…