[Java]微服务之服务保护
雪崩问题
微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩
雪崩问题产生的原因是什么?
- 微服务相互调用,服务提供者出现故障或阻塞。
- 服务调用者没有做好异常处理,导致自身故障。
- 调用链中的所有服务级联失败,导致整个集群故障
解决问题的思路有哪些?
- 尽量避免服务出现故障或阻塞
- 保证代码的健壮性
- 保证网络畅通
- 能应对较高的并发请求
- 服务调用者做好远程调用异常的后备方案,避免故障扩散
请求限流: 也叫流量整形, 限制访问微服务的请求的并发量,避免服务因流量激增出现故障。
线程隔离: 也叫做舱壁模式,模拟船舱隔板的防水原理。通过限定每个业务能使用的线程数量而将故障业务隔离,避免故障扩散。
服务熔断:由断路器统计请求的异常比例或慢调用比例,如果超出阈值则会熔断该业务,则拦截该接口的请求。
- 熔断期间,所有请求快速失败,全都走fallback逻辑。
- fallback逻辑的作用就是兜底, 让业务失败时不抛出异常, 而是返回默认数据或友好的提示
服务保护技术
Sentinel
入门
Sentinel是阿里巴巴开源的一款微服务流量控制组件。
- 官网地址: https://sentinelquard.io/zh-cn/index.html
- Sentinel 的使用可以分为两个部分:
- 核心库(Jar包):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。在项目中引入依赖即可实现服务限流、隔离、熔断等功能。
- 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。
搭建Sentinel的控制台
- 下载jar包
- 下载地址: Releases · alibaba/Sentinel · GitHub
- 也可以直接使用课前资料提供的jar包
- 运行
- 将jar包放在任意非中文、不包含特殊字符的目录下,重命名为
sentinel-dashboard.jar
- 打开cmd窗口, 然后运行如下命令启动控制台:
// java -jar sentinel-dashboard.jar 启动jar包
// -Dserver.port=8090 配置启动端口, 默认8080端口冲突
// -Dcsp.sentinel.dashboard.server=localhost:8090 控制台服务地址也要改
// -Dproject.name=sentinel-dashboard 配置项目名称
// 以上是启动命令的解释
java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
- 更多配置项: 启动配置项 · alibaba/Sentinel Wiki · GitHub
- 访问服务页面: http://localhost:8090,就可以看到sentinel的控制台了
- 需要输入账号和密码,默认都是:sentinel
- 登录后,即可看到控制台,默认会监控sentinel-dashboard服务本身:
微服务整合
- 目标: 在
cart-service
模块中整合sentinel,连接sentinel-dashboard
控制台 - 引入sentinel依赖
<!--sentinel-->
<dependency><groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 配置控制台:
spring:cloud:sentinel:transport:dashboard: localhost:8090 # sentinel控制台地址
- 访问
cart-service
的任意端点
- 重启
cart-service
,然后访问查询购物车接口, - sentinel的客户端就会将服务访问的信息提交到
sentinel-dashboard
控制台。 - 并展示出统计信息:
- 点击簇点链路菜单,会看到下面的页面:
- 簇点链路,就是单机调用链路。是一次请求进入服务后经过的每一个被Sentinel监控的资源链。
- 默认Sentinel会监控SpringMVC的每一个Endpoint(http接口)。
- 限流、熔断等都是针对簇点链路中的资源设置的。
- 而资源名默认就是接口的请求路径
- 我们的SpringMVC接口是Restful风格,因此购物车的查询、删除、修改等接口全部都是
/carts
路径
- 默认情况下Sentinel会把路径作为簇点资源的名称,无法区分路径相同但请求方式不同的接口,查询、删除、修改等都被识别为一个簇点资源,这显然是不合适的。
- 所以要修改配置,把
请求方式 + 请求路径
作为簇点资源名 cart-service
的application.yml
中添加下面的配置:
spring:cloud:sentinel:transport:dashboard: localhost:8090http-method-specify: true # 开启请求方式前缀
- 重启服务,通过页面访问购物车的相关接口,可以看到sentinel控制台的簇点链路发生了变化:
请求限流
在簇点链路后面点击流控按钮,即可对其做限流配置:
- QPS: 每秒请求次数
- 单机阈值: 触发流量控制的数值
我们利用Jemeter做限流测试,每秒发出10个请求:
- 按照资料中Jmeter稳定, 安装并熟悉工具
- 把资料中的测试文本拖入Jemeter
- 启动测试
- 查看监控结果
可以看出GET:/carts
这个接口的通过QPS稳定在6附近,而拒绝的QPS在4附近,符合我们的预期
线程隔离
限流可以降低服务器压力,尽量减少因并发流量引起的服务故障的概率,但并不能完全避免服务故障。
一旦某个服务出现故障,我们必须隔离对这个服务的调用,避免发生雪崩。
- 比如,查询购物车的时候需要查询商品,
- 为了避免因商品服务出现故障导致购物车其他服务受到影响,
- 我们可以把购物车业务中查询商品的业务隔离起来,限制可用的线程资源
- 这样,即便商品服务出现故障,最多导致查询购物车业务故障,
- 并且可用的线程资源也被限定在一定范围,不会导致整个购物车服务崩溃。
- 所以,我们要对查询商品的FeignClient接口做线程隔离。
设置线程隔离
- 5个并发线程, 如果单线程QPS为2, 则5线程QPS为10
- 也就是说这个查询功能最多使用5个线程, 如果查询商品的接口每秒处理2个请求,则5个线程的实际QPS在10左右,而超出的请求自然会被拒绝。
模拟商品查询慢服务, 配置购物车服务的tomcat的资源上限
@Api(tags = "商品管理相关接口")
@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemController {@ApiOperation("根据id批量查询商品")@GetMappingpublic List<ItemDTO> queryItemByIds(@RequestParam("ids") List<Long> ids){// 模拟业务延迟// 休眠500毫秒ThreadUtil.sleep(500);return itemService.queryItemByIds(ids);}}
server:port: 8082tomcat:threads:max: 25 # 最大线程数accept-count: 25 # 队列最大长度(线程满了在队列中等待)max-connections: 100 # 允许的最大连接数
- 查询购物车的接口处理速度比较慢, 其他增删改的接口速度是正常的
我们利用Jemeter,每秒发送100个请求, 让查询购物车接口的线程耗尽, 查看其他接口是否受影响
- 因为查询购物车业务的线程被耗尽, 导致查询购物车失败
- 但是因为做了线程隔离, 添加购物车等业务并没有被影响
- 如果不做线程隔离, 因为商品服务出现问题, 导致查询购物车接口处理非常慢
- 请求一直增加, 业务处理不完, 资源就无法释放,
- 最终导致tomcat资源被耗尽, 整个购物车所有的业务都无法访问了,
- 所以线程隔离的作用就是把可能的故障, 限制在一定范围内, 避免雪崩现象
Fallback
通过线程隔离, 可以对服务起到保护作用, 某一个业务出现问题不会影响其他业务, 但是被隔离的这个业务, 一旦出现问题, 还是会出现业务不可用的问题, 影响用户体验, 所以需要通过后备方案, 处理可能出问题的业务
针对远程调用进行线程隔离, 并设置Fallback
- 将FeignClient作为Sentinel的簇点资源(开启远程监控):
feign:okhttp:enabled: true # 开启OKHttp连接池支持sentinel:enabled: true # 开启sentinel
- FeignClient的Fallback有两种配置方式:
- 方式一: FallbackClass,无法对远程调用的异常做处理
- 方式二: FallbackFactory,可以对远程调用的异常做处理,通常都会选择这种 (推荐)
- 自定义类,实现FallbackFactory,编写对某个FeignClient的fallback逻辑
@Slf4j
public class ItemClientFallbackFactory implements FallbackFactory<ItemClient> {public ItemClient create(Throwable cause) {return new ItemClient() {@Overridepublic List<ItemDTO> queryItemByIds(Collection<Long> ids) {log.error("查询商品失败", cause);return CollUtils.emptyList();}@Overridepublic void deductStock(List<OrderDetailDTO> items) {log.error("扣减商品库存失败", cause);throw new RuntimeException(cause);}};}
}
- 可以记录一些错误日志, 设置调用失败返回的默认数据, 或者直接抛出异常, 由调用者进行处理
- 将刚刚定义的FallbackFactory注册为一个Bean
public class DefaultFeignConfig {@Beanpublic ItemClientFallbackFactory itemClientFallbackFactory(){return new ItemClientFallbackFactory();}
}
- 在接口中使用自定义FallbackFactory
@FeignClient(value = "item-service",configuration = DefaultFeignConfig.class, fallbackFactory = ItemClientFallbackFactory.class) // 指定拉取的服务名称
public interface ItemClient {@GetMapping("/items") // 指定请求方法和路径List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids); // 指定请求参数和返回值类型@PutMapping("/items/stock/deduct")void deductStock(@RequestBody List<OrderDetailDTO> items);
}
- cart-sevice服务调用hm-api中的ItemClient方法,
- 如果远程调用失败或者失败, 就会执行Fallback逻辑
- 当服务出现问题时, 最大程度的保证用户体验
- 给远程调用接口设置线程隔离
- 使用Jemeter工具耗尽查询购物车的资源, 继续使用购物车服务
- 查询购物车时, 调用商品查询服务失败, 因为商品查询服务资源耗尽
- Fallback逻辑生效, 商品业务给购物车业务返回了默认数据, 而不是抛出异常, 用户体验更稳定
服务熔断
熔断是解决雪崩问题的重要手段。思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求; 而当服务恢复时,断路器会放行访问该服务的请求。
- 作用: 服务熔断的作用就是进一步降低故障服务对网络资源的占用
- 表现: 既然服务已经出现了问题, 就不要再重复请求了, 既占用资源, 又拖慢业务响应
- 前提: 使用服务熔断的前提是配置好Fallback, 保证熔断了进入应急处理, 而不是频繁报错
点击控制台中簇点资源后的熔断按钮,即可配置熔断策略
- 资源名: 给哪个接口设置熔断规则
- 最大RT: 超过200ms被视为慢调用
- 比例阈值: 超过一半触发熔断
- 熔断时间: 熔断后20s内不再请求服务, 而是触发后备逻辑
测试一下:
- 使用Jmeter工具持续发请求, 耗尽查询商品接口的资源, 商品服务出现故障,
- 购物车服务请求商品服务时, 响应速度还是很快,
- 因为慢服务触发熔断, 直接进入后备逻辑, 而不是一直请求商品服务, 浪费网络资源
相关文章:

[Java]微服务之服务保护
雪崩问题 微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩 雪崩问题产生的原因是什么? 微服务相互调用,服务提供者出现故障或阻塞。服务调用者没有做好异常处理,导致自身故障。调用链中的所有服…...

自动驾驶目标检测融合全貌
1、early fusion 早期融合,特点用到几何空间转换3d到2d或者2d到3d的转换,用像素找点云或者用点云找像素。 2、deep fusion 深度融合,也是特征级别融合,也叫多模态融合,如bevfusion范式 3、late fusion 晚融合&#x…...
消息框(Message Box)的测试方法和测试用例
我来帮你了解消息框(Message Box)的测试方法和测试用例的编写。 我已经创建了一个测试用例示例,让我为你解释消息框测试的主要方面: 测试维度: 功能性测试:验证消息框的基本功能是否正常样式测试:确认不同类型消息框…...

Ubuntu 包管理
APT&dpkg 查看已安装包 查看所有已经安装的包 dpkg -l 查找包 apt search <package_name>搜索软件包列表,找到与搜索关键字匹配的包 dpkg与grep结合查找特定的包 dpkg -s <package>:查看某个安装包的详细信息 安装包 apt安装命令 更新…...

[Ubuntu] linux之Ubuntu18.04的下载及在虚拟机中详细安装过程(附有下载链接)
前言 ubuntu 链接:https://pan.quark.cn/s/283509d0d36e 提取码:dfT1 链接失效(可能被官方和谐)可评论或私信我重发 下载压缩包后解压 !!安装路径不要有中文 下载后解压得到.iso文件,不要放在…...

ffmpeg安装(windows)
ffmpeg安装-windows 前言ffmpeg安装路径安装说明 前言 ffmpeg的安装也是开箱即用的,并没有小码哥说的那么难 ffmpeg安装路径 这就下载好了! 安装说明 将上面的bin目录加入到环境变量,然后在cmd中测试一下: C:\Users\12114\Desktop\test\TaskmgrPlayer\x64\Debug>ffmpe…...

服务器数据恢复—raid6阵列硬盘被误重组为raid5阵列的数据恢复案例
服务器存储数据恢复环境: 存储中有一组由12块硬盘组建的RAID6阵列,上层linux操作系统EXT3文件系统,该存储划分3个LUN。 服务器存储故障&分析: 存储中RAID6阵列不可用。为了抢救数据,运维人员使用原始RAID中的部分…...
linux内核编译启动总结
linux kernel 编译 升级汇总 写在前面内核编译获取kernel代码开始前的准备工作 编译过程1\.解压与净化将下载好的linux内核解压至/usr/src 2\. 得到源代码后,将其净化3\. 配置要进行编译的内核4.编译内核. (15分钟)5.编译模块.方法1:方法2: 6…...

Android Studio的AI工具插件使用介绍
Android Studio的AI工具插件使用介绍 一、前言 Android Studio 的 AI 工具插件具有诸多重要作用,以下是一些常见的方面: 代码生成与自动补全 代码优化与重构 代码解读 学习与知识获取 智能搜索与资源推荐实际使用中可以添加注释,解读某段代…...

本地部署 WireGuard 无需公网 IP 实现异地组网
WireGuard 是一个高性能、极简且易于配置的开源虚拟组网协议。使用路由侠内网穿透使其相互通讯。 第一步,服务端(假设为公司电脑)和客户端(假设为公司外的电脑)安装部署 WireGuard 1,点此下载(…...
asyncio.ensure_future 与 asyncio.create_task:Python异步编程中的选择
asyncio.ensure_future 与 asyncio.create_task:Python异步编程中的选择 引言asyncio.ensure_futureasyncio.create_task两者的区别参数接受范围任务调度的保证代码可读性 哪个更好?使用asyncio.create_task使用asyncio.ensure_future 结论参考 引言 在…...

CTF之密码学(密码特征分析)
一.MD5,sha1,HMAC,NTLM 1.MD5:MD5一般由32/16位的数字(0-9)和字母(a-f)组成的字符串 2.sha1:这种加密的密文特征跟MD5差不多,只不过位数是40(sha256:64位;sha512:128位) 3.HMAC:这…...

JVM调优篇之JVM基础入门AND字节码文件解读
目录 Java程序编译class文件内容常量池附录-访问标识表附录-常量池类型列表 Java程序编译 Java文件通过编译成class文件后,通过JVM虚拟机解释字节码文件转为操作系统执行的二进制码运行。 规范 Java虚拟机有自己的一套规范,遵循这套规范,任…...

EXCEL截取某一列从第一个字符开始到特定字符结束的字符串到新的一列
使用EXCEL中的公式进行特定截取 假设列A是一组产品的编码,我们需要的数据是“-”之前的字段。 我们需要在B1单元格输入公式“LEFT(A1,SEARCH("-",A1)-1)”然后选中B1至B4单元格,按“CTRLD”向下填充,就可以得出其它几行“-”之前的…...

数据库期末复习题库
1. Mysql日志功能有哪些? 记录日常操作和错误信息,以便了解Mysql数据库的运行情况,日常操作,错误信息和进行相关的优化。 2. 数据库有哪些备份方法 完全备份:全部都备份一遍表备份:只提取数据库中的数据࿰…...

私有库gitea安装
一 gitea是什么 Gitea是一款自助Git服务,简单来说,就是可以一个私有的github。 搭建很容易。 Gitea依赖于Git。 类似Gitea的还有GitHub、Gitee、GitLab等。 以下是安装步骤。 二 安装sqilite 参考: 在windows上安装sqlite 三 安装git…...
关于最近win11不能使用ie,而不能使用考试客户端的解决方法
弄ie的那个我感觉是非常难的,所以我的是另一种的方法 下载360浏览器(不是360全家桶)360安全浏览器-全面保护上网安全,4亿用户共同选择(上面的是官网,不要下载错了,还有安装界面注意不要勾选一下…...

深度学习之Mask-R-CNN
1.1 Mask-RCNN 的网络结构示意图 其中黑色部分为原来的Faster-RCNN,红色部分为在Faster网络上的修改: 1)将ROI Pooling层替换成了ROIAlign; 2)添加并列的FCN层(Mask层); …...
css包含块
包含块 出现 在css中一些属性的计算可能超出你的预料,在普遍情况下会认为定位属性和百分比的宽高是根据父元素计算的,但是准确来说他们都是根据元素所在的包含块来计算的,所以掌握包含块的知识是非常关键的。 内容 在CSS中,“…...

混沌工程/混沌测试/云原生测试/云平台测试
背景 私有云/公有云/混合云等具有复杂,分布式,环境多样性等特点,许多特殊场景引发的线上问题很难被有效发现。所以需要引入混沌工程,建立对系统抵御生产环境中失控条件的能力以及信心,提高系统面对未知风险得能力。 …...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...