生产事故:线程管理不善诱发P0故障
背景
处于业务诉求,需要建立一个统一的调度平台,最终是基于 Dolphinscheduler 的 V1.3.6 版本去做二次开发。在平台调研建立时,这个版本是最新的版本
命运之轮开始转动
事故
表象
上班后业务部门反馈工作流阻塞,登录系统发现大量实例阻塞于 WAITTING_THREAD 状态,而且有比较多定时在凌晨执行的工作流,直到现在都未执行完,按往常执行效率推断应该早就执行结束了。
处理
通过该状态的触发点逻辑,可以找到是Master节点的问题,当调度线程池活跃线程打满,后续的实例都会处于WAITTING_THREAD 状态,剩下就是走流程了 dump线程 dump内存 重启节点。
分析
第一个疑点 stack中发现确实有大量线程处于 BLOCKED 和 TIMED_WAITING 状态
大量线程Block于类加载?😳
搜索后可以找到大致的原因,只能说确实问题很隐晦有性能影响,不过不会导致线程池拉满。
类似于Redis缓存中常会讨论的缓存穿透问题,此时JVM就是缓存,一堆Jar就是DB,JVM不停去扫描加载Jar去找这个不存在的驱动类,类加载又是同步的,其他线程都得等,极大影响了并发时的查询性能,恰好这里线程池又拉满了线程池中的任务都是在while(true)去查库中的数据记录的工作流状态是否执行结束,执行结束才会break
😨。
- 同事升级了MySQL驱动8.0,导致应用大量超时
- druid连接池引起的线程blocked
100多个线程处于 TIMED_WAITING ,通过栈可以看出都是在死循环查库,等工作流实例运行结束好做收尾工作
Github 代码
那为什么工作流中的任务 无法更新状态呢,导致监控任务的线程拉满,监控工作流的线程池拉满, 想通过分析内存的dump找到那几个线程池的状态和等待队列,也没看出问题,因为提交任务的时候判断了活跃线程,所以等待队列是空的,而且也没有异常的大对象,只有一堆等待回收的ZipEntry
没错 上面频繁加载Jar去找驱动类导致的
😅
此时就没头绪了,然后在MAT里瞎逛,这里看看那里点点,在看对象分布时发现有些Queue实例是没有关联到线程池的而是独立存在,逐个扫了下看等待的数量发现了突破口,有个queue积压了很多任务此时用OQL查找效率更高
,通过GCROOT看到了这个队列定义的地方和消费的逻辑。
> Github 代码
emmm 这段代码怎么说呢,如果是普通逻辑,那唯一的问题是吞了中断的异常,以及粗糙的继承Thread直接start,不利于生命周期管理。
但是这里的逻辑是为了触发更新上面两个线程池疯狂扫描的那个工作流实例表的状态,那这就有隐患了。一旦这个线程挂掉,整个系统就会逐渐不可用了,从线程stack中也确认了没这个线程,由于在应用的日志中没有看到停止和异常的日志,那就只能刚好是吞异常的地方导致线程停止了😇 墨菲定律YYDS
优化:
- 循环中catch提高到Throwable级别,把退出的事情交给 Runtime的hook实现。
- 或者用Scheduler线程池定时消费队列?这样的话即使线程挂掉了线程池也会补线程进来。
- 或者从队列消费任务后将任务提交到线程池执行
前提是队列中的事件允许无序消费
第二个疑点 只有一个Master节点出问题
Master搭建的是集群
TODO
优化
- 增加关键流程处的技术和业务指标告警,及时发现和处理问题。
- 例如关键的几个线程池一旦活跃线程达到多少阈值后就通过机器人或邮件告警相关负责人及时响应
- 加强对MAT jstack等工具的熟悉程度和异常指标的敏感度,提高解决问题效率
总结
其实前面铺垫了1.3.6版本的选择,只能说生不逢时了,因为那会这个项目还是处于孵化状态,后几年才正式发布。
现在最新的版本大部分基础技术模块都重写或优化了,包括线程和线程池管理,用 Micrometer 埋点,加入了更细致的技术指标的监控和告警。
但是从这个平台运行到现在已经有大量的调度在跑,要迁移的话就不是一个P0能扛得住了😇,这下有点船大难调头的意味了,只能在现有的架构上打补丁或者说打地鼠 DDDD。
相关文章:

生产事故:线程管理不善诱发P0故障
背景 处于业务诉求,需要建立一个统一的调度平台,最终是基于 Dolphinscheduler 的 V1.3.6 版本去做二次开发。在平台调研建立时,这个版本是最新的版本 命运之轮开始转动 事故 表象 上班后业务部门反馈工作流阻塞,登录系统发现大…...
WPF —— GDI画板
定义绘制对象 Graphics g; 起始点坐标 Point start; 画笔颜色 Color c1 Color.Black; 是否开始绘制 当flagtrue开始绘制,结束绘 private void Form1_MouseDown(object sender, MouseEventArgs e) {if (e.Button MouseButtons.Left) //点击了鼠标左键{start …...
C++:基于范围的for循环
使用迭代器遍历容器在遍历的过程中需要给出容器的两端:开头(begin)和结尾(end),因为这种遍历方式不是基于范围来设计的。在基于范围的for循环中,不需要再传递容器的两端,循环会自动以…...

引领智能互联时代,紫光展锐赋能百业创新发展
随着5G技术的快速发展,各行各业对通信技术的需求也在不断升级。紫光展锐持续深耕5G垂直行业,不断推进5G标准演进,从R15到R16,再到R17,展锐携手生态合作伙伴,不断推出创新性解决方案,在5G RedCap…...

lv_micropython to download and building
想要在ESP32-C3使用Micropython开发GUI,所以需要编译lv_micropython,当前github上的版本是9.1.0。 一、开发环境 因为编译lv_micropython需要在linux系统下,但是我的电脑是windows系统,所以我在windows系统上安装了VMware虚拟机&…...

二叉树练习day.9
669.修剪二叉搜索树 链接:. - 力扣(LeetCode) 题目描述: 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变…...
2024年第十七届“认证杯”数学中国数学建模网络挑战赛B题思路
B题 神经外科手术的定位与导航 人的大脑结构非常复杂,内部交织密布着神经和血管,所以在大脑内做手术具有非常高的精细和复杂程度。例如神经外科的肿瘤切除手术或血肿清除手术,通常需要将颅骨打开一个(或几个)圆形窗口,将病变部位暴露在术野中。但当病变部位较深时,就必…...

【vue】slot 匿名插槽 / 具名插槽
slot父组件向子组件传递数据 匿名插槽–直接写 具名插槽–指定名称 父组件中 子组件中: 代码 App.vue <template><h2>App.vue</h2><!-- 匿名插槽 --><Header><a href"1234567890.com">1234567890</a>&…...
FFmpeg: 自实现ijkplayer播放器-02环境搭建
文章目录 安装环境项目工程配置库文件 安装环境 IDE: Qt5.12 库: ffmpeg-4.2.1-win32SDL 项目工程配置 pro文件 TEMPLATE app TARGET SimpleIJKPlayer DESTDIR bin QT core gui widgets #CONFIG debug #DEFINES _UNICODE WIN64 QT_WIDGETS_LIBwin32 { LIBS -L$$PW…...

Redis从入门到精通(十七)多级缓存(二)Lua语言入门、OpenResty集群的安装与使用
文章目录 前言6.4 Lua语法入门6.4.1 初识Lua6.4.2 Hello World6.4.3 变量6.4.3.1 Lua的数据类型6.4.3.2 声明变量 6.4.4 循环6.4.5 函数6.4.6 条件控制 6.5 实现多级缓存6.5.1 安装和启动OpenResty6.5.2 实现ajax请求反向代理至OpenResty集群6.5.2.1 反向代理配置6.5.2.2 OpenR…...

pytest常用钩子函数
1、什么叫钩子函数 在Pytest框架中,钩子函数是一种允许用户扩展或者自定义测试执行过程的机制。钩子函数允许用户在测试的不同阶段插入自定义的代码,以实现特定的行为,操作或处理。这种插入式的机制使得Pytest具有高度的灵活性和扩展性。 如…...
.Net <% %>
<% %> 语法 : <% import namespace"system.data"%> 用来导入后台命名空间 指令用于指定当页和用户控件编译器处理 ASP.NET Web 窗体页 (.aspx) 和用户控件 (.ascx) 文件时所使用的设置。<% %> 语法 : <% name %> <% getstr() %&g…...

【C语言__编译和链接__复习篇2】
目录 前言 一、翻译环境和运行环境 二、翻译环境 2.1 预处理 2.1 编译 2.1.1 词法分析 2.1.2 语法分析 2.1.3 语义分析 2.2 汇编 2.3 链接 三、运行环境 四、简答主线问题 前言 本篇主要讨论以下问题: 主线问题: 1. 源文件(.c)如何转换成(.exe)文件…...

Jmeter —— 自动录制脚本
1、Jmeter配置 1.1新增一个线程组 1.2Jmeter中添加HTTP代理 1.3配置HTTP代理服务器 修改端口 修改Target Cintroller(目标控制器) 修改Grouping(分组) 编辑录制中的包含和排除 在“URL Patterns to include包含模式”中填入.*(123456).*用以过滤请求地址中不包含123456的请求…...
使用python互相转换AVI、MP4、GIF格式视频文件
一、AVI文件转MP4文件 要将AVI格式的视频转换为 MP4,你可以使用 Python的 moviepy 库。以下是一个示例代码,用于将 AVI 文件转换为 MP4 文件: from moviepy.editor import VideoFileClip# 读取 AVI 文件 clip VideoFileClip("input.a…...

11 Php学习:函数
PHP 内建函数Array 函数 PHP Array 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。 创建 PHP 函数 当您需要在 PHP 中封装一段可重复使用的代码块时,可以使用函数。下面详细解释如何创建 PHP 函数并举例说明。 创建 PHP 函数的语法 PHP 函数的基…...
查询电脑用户名和组信息
在命令行里查看电脑名: c:\>hostname 在命令行里,查看组信息: # 显示本地所有的用户组 c:\>net localgroup #显示administrators组包含的用户信息 c:\>net localgroup administrators # 比如我的显示信息: C:\>ne…...

【Godot4.2】CanvasItem绘图函数全解析 - 9.绘制表格
概述 之前介绍TextLine和TextParagraph的时候,提到了用制表符和设定列宽形式来绘制简易表格,但是很明显,单纯使用此种方式很难获得对表格的精确控制。 所以对于表格绘制问题,我决定单独开坑,单独深入研究。 目前比较…...

部署HDFS集群(完全分布式模式、hadoop用户控制集群、hadoop-3.3.4+安装包)
目录 前置 一、上传&解压 (一 )上传 (二)解压 二、修改配置文件 (一)配置workers文件 (二)配置hadoop-env.sh文件 (三)配置core-site.xml文件 &…...

TCP协议简单总结
TCP:传输控制协议 特点:面向连接、可靠通信 TCP的最终目的:要保证在不可靠的信道上实现可靠的传输 TCP主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接 三次握手建立可靠…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...