分享---rpc运维事故处理

事故案例03 - Qserver RPC调用大量失败

一、事故背景

Queryserver是内部的核心服务,负责处理数据查询请求并支持分布式缓存功能。为优化缓存一致性,新增了分布式锁逻辑:在查询请求命中缓存时需先获取分布式锁(基于Tair实现),若未获取成功则等待1秒后重试。此功能上线后,在特定异常场景下(如SQL执行失败)触发了线程池资源耗尽,最终导致RPC请求被拒绝,引发服务故障。

二、事故影响

(一)业务影响

  • 线上部分数据查询失败,直接影响依赖Queryserver的业务功能(如Mustang、malldatacentor服务)。
  • 因故障快速修复(总影响时长19分钟),未造成大规模客户投诉,但存在潜在业务中断风险。
  • 某日线上出现RPC失败率突增,导致部分业务数据无法展示。

(二)技术影响

  • 告警显示上游服务调用Queryserver的RPC失败率超过50%,Queryserver的RPC线程池持续满载,触发RejectedException(服务端线程池拒绝请求),服务可用性下降。
  • 失败请求均匀分布,无明显业务流量突增或数据库负载异常,即Doris引擎负载无显著波动,故障范围集中在Queryserver自身逻辑。

三、根本原因

(一)直接原因

分布式锁逻辑在高并发场景下导致RPC线程池耗尽,RPC框架主动拒绝请求(RejectedException)。

(二)深层原因

1. 逻辑设计缺陷
  • 查询失败时未缓存结果,后续相同请求持续触发分布式锁竞争,强制串行执行,占用线程资源。
  • 分布式锁重试间隔过长(1秒),导致线程长时间阻塞,加速线程池耗尽。
2. 异常处理不足

未对失败查询的请求进行熔断或限流,异常流量持续冲击线程池。

3. 测试覆盖不全

未模拟“高并发异常SQL”场景,导致逻辑缺陷未在测试阶段暴露。

四、处理流程与数据变化

(一)处理流程

  • 16:16:收到raptor持续告警,确认Mustang/malldatacentor服务异常。
  • 16:17:通过链路追踪定位到Queryserver RPC失败率异常。
  • 16:28:尝试重启服务,但未解决问题。
  • 16:32:深入分析代码逻辑,发现分布式锁机制导致线程池满载,临时关闭缓存功能或调整锁等待时间。
  • 16:35:告警恢复,服务可用性回升。

(二)关键数据变化

指标故障前故障中恢复后
Queryserver QPS正常骤降(拒绝请求)正常
RPC失败率<1%>50%<1%
线程池使用率60%100%60%
Tair锁竞争频率高频(持续重试)

五、过程复现

(一)原因定位

queryserver添加了分布式锁的功能,如果开启了缓存的情况下,每个查询需要去拿到分布式锁之后,才能被执行,否则会等待1s时间再去尝试拿到分布式锁。代码如下:

while (true) {if (!cacheInfo.isUpdateCache()) {//1 从缓存中获取结果CachedResult cachedResult = cacheService.getResult(sqlMappingKey);if (cachedResult!= null) {
//                logInfo.setHitCache(true);detailLog.setUseCache(cacheInfo.isFetchFromCache());return ResponseContext.success(cachedResult.getData()).hitCache().withAttach(detailLog);}}//加锁if (!tairService.setNx((LOCK_PREFIX + sqlMappingKey).getBytes(), ("" + id).getBytes(), 20)) {Thread.sleep(1000);continue;}//2 从引擎中查询List result = queryEngineBackend.syncQuery(queryInfo);//3 对结果进行缓存if (result!= null &&!result.isEmpty()) {//这里最终判断传入的缓存过期时间是否合法,如果不合法就传入默认的1800s.最长时间不超过60天cacheService.cacheResult(sqlMappingKey, result, ((cacheInfo.getExpireMs() > 0) && (cacheInfo.getExpireMs() < MAX_EXPIRE_SEC))? cacheInfo.getExpireMs() : DEFAULT_EXPIRE_SEC);}//解锁if (("" + id).equals(new String(tairService.getValue((LOCK_PREFIX + sqlMappingKey).getBytes()))))tairService.delete((LOCK_PREFIX + sqlMappingKey).getBytes());return ResponseContext.success(result).withRequestId(id).withAttach(detailLog);
}

并且如果查询失败的话,不会缓存SQL结果,后续的相同请求均会提交到引擎执行,而后续的请求如果全是有问题的SQL,则会占用请求线程,并且将查询变为串行执行。

(二)复现过程

通过监控发现,RPC线程池使用率在故障期间持续100%,队列堆积后触发拒绝策略。

复现实验:构造高并发异常SQL请求,线程池在10秒内被打满,完全复现线上问题。

  1. 在Mustang上配置一个带有缓存功能的SQL,然后SQL故意写成执行会报错的SQL。
  2. 在st环境使用工具并发请求,查看queryserver报错信息。

实验结果如下:

  1. queryserver大量出现RPC请求被拒绝,出现很多com.dianping.pigeon.remoting.provider.exception.ProcessTimeoutException异常。
  2. 上游调用出现失败率较高的情况。

六、总结与改进方案

(一)深层次原因分析

1. 架构设计缺陷
  • 资源竞争模型不合理:
    • 分布式锁重试机制采用同步阻塞(Sleep),违背高并发服务的异步化设计原则。
    • 未隔离线程池:锁竞争、SQL查询、缓存操作共享同一线程池,异常SQL影响全局请求。
  • 缓存策略漏洞:
    • 仅缓存成功结果,未对失败请求做短期标记(如“异常状态缓存”),导致无效查询重复执行。
2. 运维与监控盲区
  • 线程池状态未监控:仅关注QPS和错误率,未实时跟踪线程池使用率、锁竞争耗时等指标。
  • 告警阈值不合理:RPC失败率告警触发阈值过高(>30%),未能提前预警。
3. 测试与流程问题
  • 异常场景覆盖不足:压力测试仅覆盖正常SQL,未模拟高并发异常SQL场景。
  • 代码评审遗漏:分布式锁逻辑的Sleep操作在评审中未被质疑,团队对阻塞风险认知不足。

(二)技术解决方案(面试重点)

1. 逻辑优化
  • 锁重试异步化:
    • Thread.sleep(1000)改为异步等待(如基于CompletableFuture的调度),释放线程资源。
    • 代码示例:
if (!tairService.setNx(...)) { return CompletableFuture.delayedExecutor(100, TimeUnit.MILLISECONDS) .submit(() -> retryLockAndQuery()); 
}
  • 失败结果缓存:
    • 对异常SQL结果缓存5秒,避免重复执行,代码修改:
if (result == null) { cacheService.markError(sqlMappingKey, 5); // 标记异常状态 
}
2. 架构增强
  • 线程池隔离:
    • 为锁竞争、SQL查询、缓存操作分配独立线程池,避免相互影响。
  • 使用Netty或Vert.x实现异步RPC框架,提升吞吐量。
3. 熔断与限流
  • 集成Hystrix,对异常SQL请求熔断(10秒内错误率>50%则直接拒绝)。
  • 为单SQL设置QPS限流(如每秒100次),防止资源耗尽。
4. 监控与运维改进
  • 新增监控指标:
    • 线程池使用率、锁竞争耗时、Tair操作成功率。
    • 通过Prometheus + Grafana实时展示,阈值触发企业微信告警。
  • 混沌测试常态化:
    • 定期注入线程池满载、分布式锁失效等故障,验证服务自愈能力。

七、后续计划

  • 灰度发布改进后的分布式锁逻辑,验证异常场景下的线程池稳定性。
  • 完善自动化测试平台的异常注入能力(如模拟SQL失败、线程池满载)。
  • 建立服务健康度评分体系,将线程池状态、锁竞争等指标纳入服务可用性评估。

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

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

相关文章

string类详解(下)

文章目录 4. string类的模拟实现4.1 构造 析构4.2 c_str4.3 下标遍历4.4 迭代器4.5 插入4.6 删除4.7 查找4.8 赋值4.9 交换4.10 提取子串4.11 比较大小4.12 流插入 && 流提取 5. 现代版写法的String类5.1 完整代码 6. 写时拷贝&#xff08;了解&#xff09; 4. string…

win11本地部署deepseek大模型(安装ollama+docker+open-webui)最终实现自己的项目可通过API调用投喂数据后的模型

硬件配置&#xff1a;笔记本win11&#xff0c;内存32G&#xff0c;CPU锐龙7 &#xff0c;无独显&#xff1b;只能考虑deepseek-r1:1.5b模型。 第一步&#xff1a;安装Ollama 此处不过多累赘了&#xff0c;https://ollama.com/官网选择对应的系统版本下载即可。 需要注意的是…

WebSocket简单介绍 并接入deepseek

目录 什么是 WebSocket&#xff1f;工作原理&#xff1a; 为什么需要 WebSocket&#xff1f;WebSocket 的优势HTTP 和 WebSocket 的区别WebSocket 的劣势WebSocket 的应用场景WebSocket 握手过程1. 客户端发起握手请求2. 服务器响应握手请求3. 建立连接 WebSocket 事件处理WebS…

虚拟机安装教程

一、软件下载与安装 运行安装程序: 双击下载的.exe文件&#xff0c;运行安装程序。 按照安装向导的提示进行操作。 通常情况下&#xff0c;你需要接受许可协议&#xff0c;选择安装目录&#xff08;建议使用默认路径&#xff0c;除非你有特殊需求&#xff09;&#xff0c;并选…

order by布尔盲注、时间盲注

pdo防御下&#xff0c;order by、limit不能参数绑定&#xff0c;可以进行sql注入 案例&#xff1a;靶场的less-46 布尔盲注&#xff1a; import requests from lxml import htmldef get_id_one(URL, paload):res requests.get(urlURL, paramspaload)tree html.fromstring(…

springboot集成deepseek4j

1、文档地址 快速开始 - 零基础入门Java AI 免费的模型 Models 2、pom文件依赖 parent依赖 <dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.12.0</version></dependency>&…

Visual Studio Code 跨平台安装与配置指南(附官方下载链接)

一、软件定位与核心功能 Visual Studio Code&#xff08;简称VS Code&#xff09;是微软开发的开源跨平台代码编辑器&#xff0c;支持超过50种编程语言的智能补全、调试和版本控制功能。2025版本新增AI辅助编程模块&#xff0c;可自动生成单元测试代码和API文档注释。 二、下载…

elementplus点击按钮直接预览图片

引用&#xff1a;https://blog.csdn.net/this_zq/article/details/134535539 <el-image-viewerv-if"showImagePreview":zoom-rate"1.2"close"closePreview":url-list"imgPreviewList"/>const showImagePreview ref(false) cons…

grafana K6压测

文章目录 install and runscript.jsoptions最佳实践 report 解析 https://grafana.com/docs/k6/latest/get-started install and run install # mac brew install k6当前目录下生成压测脚本 # create file script.js k6 new [filename] # create file ‘script.js’ in …

解决IDEA使用Ctrl + / 注释不规范问题

问题描述&#xff1a; ctrl/ 时&#xff0c;注释缩进和代码规范不一致问题 解决方式 设置->编辑器->代码样式->java->代码生成->注释代码

项目实践 之 pdf简历的解析和填充(若依+vue3)

文章目录 环境背景最终效果前端讲解左侧模块解析右侧上传模块解析前端步骤 后端讲解代码前端 环境背景 若依前后端分离框架 vue最后边附有代码哦 最终效果 前端讲解 左侧模块解析 1、左侧表单使用el-form 注意&#xff1a; 1、prop出现的字段&#xff0c;需要保证是该类所…

【Electron入门】进程环境和隔离

目录 一、主进程和渲染进程 1、主进程&#xff08;main&#xff09; 2、渲染进程&#xff08;renderer&#xff09; 二、预加载脚本 三、沙盒化 为单个进程禁用沙盒 全局启用沙盒 四、环境访问权限控制&#xff1a;contextIsolation和nodeIntegration 1、contextIsola…

如何看待 Kaiming He 最新提出的 Fractal Generative Models ?

何恺明团队提出的分形生成模型(Fractal Generative Models) 引发了广泛关注,其核心思想是通过递归调用生成模型模块构建自相似结构,类似数学中的分形概念(如雪花结构),从而高效生成高分辨率数据(如图像)。 Fractal Generative Models即分形生成模型,是一种新型的生成…

Debian系统终端输入ifconfig报错

报错 bash: ifconfig: command not found 原因 Debian 上默认不安装 ifconfig 软件包。这是因为 ifconfig 已被弃用&#xff0c;取而代之的是新的 ip 命令。该 ip 命令现在负责修改或显示路由、网络设备、接口和隧道 如果仍然想使用旧的 ifconfig 命令&#xff0c;则必须显式…

【NLP 27、文本分类任务 —— 传统机器学习算法】

不要抓着枯叶哭泣&#xff0c;你要等待初春的新芽 —— 25.1.23 一、文本分类任务 定义&#xff1a;预先设定好一个文本类别集合&#xff0c;对于一篇文本&#xff0c;预测其所属的类别 例如&#xff1a; 情感分析&#xff1a; 这家饭店太难吃了 —> 正类 …

Lumoz Chain正式上线:AI 时代的新算力破局者

新的叙事和技术突破永远是推动行业前行的核心动力。当下&#xff0c;AI Agent无疑是最炙手可热的赛道之一。 当加密世界将目光投向AI领域时&#xff0c;大多数项目仍停留在以AI为工具或应用场景的层面&#xff0c;试图通过集成AI模型或优化链上功能来吸引用户。然而&#xff0c…

Python - Python连接数据库

Python的标准数据库接口为&#xff1a;Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。 PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个实现库&#xff0c;Python2中则使用mysqldb。 PyMySQL 遵循 Python 数据库 API v2.0 规范&…

面试八股文--数据库基础知识总结(1)

1、数据库的定义 数据库&#xff08;DataBase&#xff0c;DB&#xff09;简单来说就是数据的集合数据库管理系统&#xff08;Database Management System&#xff0c;DBMS&#xff09;是一种操纵和管理数据库的大型软件&#xff0c;通常用于建立、使用和维护数据库。数据库系统…

关于在java项目部署过程MySQL拒绝连接的分析和解决方法

前言 在最近一次部署项目一次项目部署过程中&#xff0c;由于没有对MySQL数据库的部分权限和远程连接进行授权&#xff0c;导致了在执行项目功能API时&#xff0c;出现MySQL连接异常或MySQL拒绝连接的问题。 问题 以下是部分报错截图&#xff1a; 分析 根据日志提示&#xf…

PhotoLine绿色版 v25.00:全能型图像处理软件的深度解析

在图像处理领域,PhotoLine以其强大的功能和紧凑的体积,赢得了国内外众多用户的喜爱。本文将为大家全面解析PhotoLine绿色版 v25.00的各项功能,帮助大家更好地了解这款全能型的图像处理软件。 一、迷你体积,强大功能 PhotoLine被誉为迷你版的Photoshop,其体积虽小,但功能却…