资讯动态

MongoDB Hang Analyzer 完全指南:诊断超时与进程挂起的核心工具

发布时间:2026/9/12 20:58:55 来源:尧图企业网站定制
MongoDB Hang Analyzer 完全指南诊断超时与进程挂起的核心工具【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo导读Hang Analyzer挂起分析器是 MongoDB 开源仓库中用于诊断 Evergreen 测试任务超时、进程挂起等问题的一线工具。它能够在进程疑似挂起时自动或手动收集 core dump、线程栈、锁信息等关键证据帮助开发者快速定位死锁、卡死或资源争用问题。读完本文你将掌握 hang-analyzer 子命令的完整调用方式、进程筛选规则、数据采集流程、各平台实现差异以及配套的 core analyzer离线分析与 fast_archive并行压缩上传工具的实战用法。什么是 Hang AnalyzerHang Analyzer 是一个用于从疑似挂起的进程中收集 core dump 及其他诊断信息的工具。在 EvergreenMongoDB 的 CI 系统中任何超过其超时时间的任务都会被自动进行挂起分析收集到的信息会被压缩并上传到 S3 存储。该工具的实现核心位于 buildscripts/resmokelib/hang_analyzer/hang_analyzer.py其模块 docstring 将其描述为 A prototype hang analyzer for Evergreen integration to help investigate test timeouts并明确了三大设计目标脚本支持对进程执行 dump转储以及/或者输出关于进程的有用信息摘要脚本遍历一组有趣进程interesting processes列表并对每个进程运行第一步的工具进程列表可以通过命令行选项提供Java 进程将使用jstack如果可用进行转储。工具支持 Linux、macOS X 和 Windows 三大平台是 resmoke 测试框架的一个子命令插件通过 buildscripts/resmokelib/hang_analyzer/plugin.py 注册。何时触发挂起分析Hang Analyzer 有两种典型触发场景Evergreen 任务超时任何任务运行时间超过其超时上限Evergreen 会自动运行 hang-analyzer收集的诊断信息经压缩后上传至 S3本地手动调用开发者可以随时在本地针对正在运行的进程执行同样的诊断流程此时没有超时限制。此外在 Evergreen 中当任务正常失败时Linux 内核也可能生成 core dump 并放入工作目录供后续的 core analyzer 进行离线分析。命令行调用方式非 Jepsen 任务的通用调用对于所有非 Jepsen 任务通用调用命令为buildscripts/resmoke.py hang-analyzer -o file -o stdout -m exact -p python其中python需要替换为你实际使用的 Python 二进制名称可能是以下之一平台Python 二进制名Unix/Linuxpython、python3WindowsPython、Python3注意-o file -o stdout表示调试器的输出同时写入文件与标准输出该选项可以多次指定以将输出写到多个位置。Jepsen 任务的调用对于 Jepsen 测试任务调用命令为buildscripts/resmoke.py hang-analyzer -o file -o stdout -p dbtest,java,mongo,mongod,mongos,python,_test该命令将-pprocess names指定为逗号分隔的进程名列表直接覆盖默认的有趣进程集合见下文。命令行参数详解hang-analyzer 子命令的参数由 buildscripts/resmokelib/hang_analyzer/plugin.py 中的add_subcommand注册完整参数如下短参数长参数作用默认值-m--process-match进程名匹配方式可选contains或exact匹配前会将进程名转为小写并去掉文件扩展名如 Windows 的.execontains-p--process-names逗号分隔的待分析进程名列表内置默认列表-g--go-process-names逗号分隔的 Go 进程名列表会被并入有趣进程并在分析后以 SIGABRT 结束空-d--process-ids逗号分隔的 PID 列表指定后覆盖-p与-g无-c--dump-core为每个被分析进程转储 core 文件False-s--max-disk-usage-percent允许进行 core dump 的最大磁盘占用百分比超出则跳过转储90-o--debugger-output调试器输出位置可选file或stdout可多次指定仅stdout-k--kill-processes分析完成后杀死被分析的进程False-t--task-id给定 Evergreen 任务 ID用于获取对应的符号文件无进程匹配-m的内部实现位于 buildscripts/resmokelib/hang_analyzer/process_list.py 的_pname_match函数exact要求进程名与列表项完全相等contains则要求列表项是进程名的子串。有趣进程Interesting Processes的判定规则有趣进程是 hang analyzer 检测并针对其执行操作的目标进程集合。判定规则因任务类型而异。Jepsen 任务任务名称包含 jepsen 时任何进程名与dbtest, java, mongo, mongod, mongos, python, _test中某一项完全匹配的进程都是有趣进程。其他所有场景包括本地使用 hang-analyzer 的情况有趣进程是以下两类之一以python或live-record开头的进程作为 resmoke 的子进程被派生spawn出来的进程。从源码结构看内置的默认进程名列表在 hang_analyzer.py 的HangAnalyzer.__init__中定义为mongo, mongod, mongos, _test, dbtest注释说明特意移除了python与java以避免 hang analyzer 被多次调用时重复分析自身。若通过-p显式提供进程名则会覆盖此默认列表。进程枚举的底层实现process_list.py提供了三个平台的进程列表实现_LinuxProcessList调用ps -eo pid,args获取进程信息_DarwinProcessList调用ps -axco pid,comm_WindowsProcessList调用system32\tasklist.exe /FO CSV。所有进程名会被统一转成小写process.name.lower()以便处理 macOS 上 Python 进程路径形如/System/Library/.../Python导致的大小写不一致问题。查找进程时会跳过 hang analyzer 自身os.getpid()如果指定了 PID 列表而某些 PID 并未运行会输出警告。SIGUSR1 / SetEvent 信号机制resmoke 子命令hang-analyzer会发送SIGUSR1Unix或调用SetEventWindows来通知 resmoke触发其执行以下动作打印所有 Python 线程的栈回溯stack traces为所有非 Python 子进程收集 core dump 及其他信息见下文数据采集向 Python 子进程再次发送信号让它们执行同样的操作。这一信号处理逻辑实现在 buildscripts/resmokelib/sighandler.py_handle_sigusr1会先快照当前 resmoke 派生出的所有子进程 PID_get_pids()再调用_dump_and_log转储全部线程栈、写出 report 文件并记录 suite 摘要最后对子进程 PID 列表重新发起 hang-analyzer 分析_analyze_pids使用-c -o file -o stdout -k -d pid1,pid2,...。在 Windows 上sighandler.py通过命名事件对象Global\Mongo_Python_pid实现同样功能而 process.py 中的signal_event_object会打开该事件并调用SetEventsignal_python在发送信号后还会等待 5 秒让进程完成报告。数据采集流程数据采集按以下顺序执行对应 hang_analyzer.py 中execute方法的实际流程暂停所有非 Python 进程——防止 hang analyzer 附加attach到进程时进程脱困unstuck影响现场还原在非 Sanitizer 构建上抓取调试符号向 Python 进程发送信号——resmoke.py 进程收到信号后会生成report.json因此必须在附加其他进程之前完成尽可能多地转储 core直到超过磁盘配额。默认配额为总卷空间的90%即-s参数的默认值由_check_enough_free_space使用psutil.disk_usage(.)检查当前磁盘使用百分比收集额外的非 core 数据理想情况下包括打印 C 栈回溯打印 MozJS 栈回溯JavaScript转储锁/互斥锁locks/mutexes信息转储 Server Sessions转储 Recovery Units转储存储引擎Storage engine信息对 Java 进程Jepsen 测试使用jstack转储对 Go 进程发送 SIGABRTUnix/ terminateWindows——确保其打印出栈回溯并在 POSIX 系统上退出Windows 上 Python 将 SIGABRT 模拟为TerminateProcess。需要说明的是上述非 core 数据列表仅在 Linux 上完全准确其他平台只执行其中的一部分操作。此外hang analyzer 受 Evergreen 的 post task 超时限制可能没有足够时间收集全部信息就被 Evergreen agent 终止。本地运行时没有超时限制因此 hang analyzer 反而可能讽刺性地无限挂起hang indefinitely。磁盘配额与超时控制默认 core dump 磁盘配额为 90% 总卷空间-s参数见 plugin.py。空间不足时hang analyzer 会跳过剩余进程的转储并记录日志Not enough space for a core dump, skipping ...Dumper基类dumper.py设置了转储时间预算本地运行无 Evergreen 任务 ID为 24 小时Evergreen 环境下整个 hang-analyzer 共 15 分钟其中转储阶段预算为12 分钟每次转储都会从剩余预算中扣除实际耗时。进程清理分析结束后若指定了-kteardown_processes会对未能成功转储 core 的进程发送 SIGABRT并resume以便内核完成 dump对其余进程执行kill随后_await_cores会以 60 秒为上限轮询等待 core 文件落盘每次休眠 5 秒参考TYPICAL_MONGOD_DUMP_SECS若未指定-k则恢复所有被暂停的非 Python 进程。平台实现各操作系统的 Dumper平台相关的数据采集细节由 buildscripts/resmokelib/hang_analyzer/dumper.py 中的 dumper 对象处理get_dumpers会根据sys.platform选择对应实现平台Dumper 实现调试器/工具LinuxGDBDumpergdb优先在/opt/mongodbtoolchain/v5/bin、/opt/mongodbtoolchain/v4/bin、/usr/bin中查找macOSLLDBDumperlldb在/usr/bin查找要求 XCode 7.2即 lldb-340WindowsWindowsDumpercdb.exeWindows Kits Debuggersx64Java非 WindowsJstackDumperjstackJDK 自带在/usr/bin查找JavaWindowsJstackWindowsDumper当前不支持仅输出警告平台无关兜底SigabrtDumper直接发送SIGABRT由操作系统生成 coreLinuxGDBDumperGDBDumper是功能最完整的实现其转储与非转储命令都很有代表性core 转储使用gcore dump_进程名.pid.core命令附加时设置handle SIGSTOP ignore noprint并开启set scheduler-locking on在执行会触发被附加进程内代码的命令前锁定调度器。核心转储采用--readnever参数启动 gdb避免在转储前加载调试符号浪费大量时间源码注释专门解释了这一点针对 mongo 进程的特殊处理若检测到jsscope_debug_pid.yml文件会尝试通过buildStackStringForGdb打印 JSScope 实例的 JavaScript 栈回溯set unwind-on-signal on用于在触发 SIGSEGV 时优雅恢复非转储信息采集执行一系列 MongoDB 专属 GDB 扩展命令包括mongodb-uniqstack mongodb-bt-if-active——打印唯一线程栈mongodb-dump-locks、mongodb-show-locks——转储锁/互斥锁信息mongodb-waitsfor-graph——生成等待图输出debugger_waitsfor_进程_pid.gvmongodb-javascript-stack——打印 MozJS 栈mongod-dump-sessions——转储 Server Sessionsmongodb-dump-recovery-units——转储 Recovery Unitsmongodb-dump-storage-engine-info——转储存储引擎信息同时还会执行info sharedlibrary、info threads并将原始栈thread apply all bt与处理后输出分别写入独立的日志文件Sanitizer 构建下的兜底当设置了ASAN_OPTIONS或TSAN_OPTIONS时get_dumpers会改用SigabrtDumper带GDBDumper作为 fallback以避免调试器附加导致高内存占用和臃肿的 core 文件live backtracedump_live_backtraces可在不转储 core 的情况下对运行中的进程采集栈回溯整个进程集合共享 360 秒BACKTRACE_TIMEOUT_SECONDS预算输出流式写入日志超时仍保留部分栈信息。macOSLLDBDumperLLDBDumper通过lldb --source 命令文件方式执行命令。转储 core 使用process save-core dump_进程名.pid.core信息采集包括target modules list与thread backtrace all。附加/分离前后分别执行kill -CONT/kill -STOP控制进程状态。若某个 PID 未能生成 core 文件会抛出DumpError记录需要兜底处理的 PID。WindowsWindowsDumperWindowsDumper使用cdb.exe以-c 命令 -p pid方式附加。core 转储使用.dump /ma dump_进程名.pid.mdmp.mdmp扩展名信息采集包括!peb进程环境块、lm已加载模块、!uniqstack -pn所有唯一线程及函数参数、!cs -l所有被锁定的关键段。Windows 也支持通过analyze_cores/analyze_core对.mdmp文件进行离线分析需匹配同名.exe与.pdb符号文件。SigabrtDumper平台无关兜底当找不到任何调试器时SigabrtDumper直接发送 SIGABRT让操作系统内核生成 core dump。它带有 2 分钟宽限期SIGABRT_GRACE因为阻塞在自己的信号处理路径内的进程永远不会响应 SIGABRT等待无果后若存在 fallback dumper 则回退到调试器采集栈回溯仅 backtrace不再转储 core。JstackDumper对 Java 进程执行jstack -l pid输出 Java 线程栈。核心分析器Core Analyzer离线分析 core dump除了实时挂起分析仓库还提供了配套的core analyzer子命令用于对已生成的 core dump 文件进行离线分析入口为 buildscripts/resmokelib/hang_analyzer/core_analyzer.py。本地分析python3 buildscripts/resmoke.py core-analyzer默认在build/install目录下查找二进制文件并在当前目录查找 core dump。若环境不同可通过--install-dir与--core-dir指定其他位置。分析 Evergreen 任务的 core dumppython3 buildscripts/resmoke.py core-analyzer --task-id{task_id}该命令会从指定任务下载全部 core dump 与二进制文件到--working-dir默认core-analyzer目录所有分析结果写入工作目录下的analysis子目录。注意若本地环境与任务运行时的 AMIAmazon Machine Image不同部分分析可能失败。任务 ID 已下载时会跳过重复下载。平台支持现状当前 core analyzer 仅在 Linux 上运行。Windows 仍使用旧的 hang analyzer待遇到问题或有时间后切换macOS 尚未解决获取 core dump 的问题因此该操作系统上没有 core dump 分析能力。分析流程与产物GDBDumper.analyze_core的离线分析流程见 dumper.py相当完整从 core dump 中解析生成它的二进制名Core was generated by ...正则在 install 目录或多版本测试的 multiversion 目录查找对应二进制若带版本号则从 multiversion 目录获取找不到时记录 warning 并跳过core dump 可能来自非 mongo 进程先运行一次 gdb 预热 index cacheset index-cache enabled避免同一进程中创建与读取缓存导致的异常慢速加载gdbmongo并注册 MongoDB 专属 pretty printer依次输出info threads、backtracesthread apply all bt、uniqstack、show_locks、dump_sessions、dump_recovery_units、dump_locks等分析文件到analysis目录同时会把 hang analyzer 在线阶段生成的debugger_jsscope_pid_*.txtJS 栈回溯文件复制进分析目录。每个 core dump 的分析结果汇总为 Report含 status/exit_code/耗时core analyzer 任务通过 gen_hang_analyzer_tasks.py 在 Evergreen 中动态生成。Evergreen 集成与归档上传任务超时时的自动化流程当 Evergreen 任务超时会命中 Evergreen 配置的 timeout 段运行 hang-analyzerpython3 buildscripts/resmoke.py hang-analyzer -o file -o stdout -m exact -p python其作用是在机器上查找所有 python 进程这里专门找 resmoke并发送信号。resmoke 被信号触发后会再次以自身子进程的具体 PID 调用 hang analyzer典型形式为python3 buildscripts/resmoke.py hang-analyzer -o file -o stdout -k -c -d pid1,pid2,pid3其中-k表示分析后杀死进程-c表示转储 core生成的 core dump 放入当前运行目录。测试超时的分析范围可选的测试超时参数--testTimeoutN秒可让 resmoke 在某个测试超时时对与该测试相关的所有进程执行 hang-analyzer分析范围包括测试用例创建的进程测试用例进程的任何子进程任何含有该测试唯一环境变量标记的进程与任一子进程同进程组的进程仅 Unix该 job fixture 产生的进程。一个典型进程树示例|-python resmoke.py (pgid 5) | |-mongo (ENV_MARKER0, pgid 6) | | |-foo (ENV_MARKER0, pgid 6) | | |-bar (ENV_MARKER0, pgid 7) | |-mongo (ENV_MARKER1, pgid 8) | |-mongo (ENV_MARKER2, pgid 9)注意若某个进程如示例中的bar一样被创建在新的进程组中macOS 上可能漏掉它——如果foo崩溃/退出bar会成为孤儿并被重新挂到init进程下它不再是子进程且 macOS 开启 System Integrity ProtectionSIP后通常无法读取任意进程的环境变量。非标准归档方式与 fast_archiveEvergreen 使用一种非标准方式上传 core dump原因是为了解决通过标准 Evergreen 命令归档上传时的超时问题SERVER-73171。调查发现压缩上传慢有三大原因将所有 core dump 打包进一个 tar 文件占用大量磁盘 IO且磁盘 IO 是瓶颈gzip 是单线程的同步上传大文件不快。解决方案是 buildscripts/fast_archive.py并行 gzip 压缩所有 core dump再逐个异步上传到 S3。脚本核心的process_file函数使用gzip.open逐文件压缩为.gz主流程通过concurrent.futures线程池并行处理源码采用glob匹配文件Windows/Cygwin 下还会用cygpath -wa解析符号链接路径从根本上绕开了上述三个瓶颈。自动生成 core analyzer 任务在 Evergreen 的 post task 段定义了用于生成 core analyzer 任务的函数。脚本 gen_hang_analyzer_tasks.py 会在**每个任务无论成败**上运行独立于任务之前发生的任何其他操作并检查是否应该运行这些检查包括任务运行的操作系统是否被 core analyzer 支持任务是否有已上传并附加的 core dump上传的二进制中至少有一个是 core analyzer 已知能处理的。脚本输出符合 Evergreen 格式的 JSON 文件通过generate.tasks命令生成新任务随后另一个脚本找到刚生成的任务并将其附加到当前运行的任务上。之所以要在原任务进行中上传一个临时文件是因为 Evergreen 目前不支持在任务运行结束之后向其附加文件因此需要借助 S3 文件链接在任务进行中完成挂接。实践建议与注意事项本地诊断挂起进程当你在本地遇到 resmoke 测试挂起时可直接运行# 分析所有 resmoke 子进程输出到文件与 stdout同时转储 core buildscripts/resmoke.py hang-analyzer -o file -o stdout -k -c -d $(pgrep -f resmoke | tr \n ,)若只想查看栈信息而不转储 core去掉-c即可注意本地运行没有超时限制工具可能长时间不结束可结合timeout命令使用。解读产物文件debugger_进程名_pid.log——调试器输出-o file时生成dump_进程名.pid.coreLinux/macOS或dump_进程名.pid.mdmpWindows——core 转储debugger_waitsfor_进程_pid.gv——等待图Graphviz 格式可直观展示锁等待关系debugger_jsscope_pid_i.txt——JSScope 实例的 JS 栈回溯。关键约束非 core 数据的完整采集目前仅在 Linux 上保证macOS/Windows 只执行子集core analyzer 仅支持 LinuxWindows 沿用旧 hang analyzerSanitizer 构建设置了ASAN_OPTIONS/TSAN_OPTIONS下会改用 SIGABRT 兜底而非调试器附加以避免高内存占用与超大 core 文件Evergreen 环境下的 hang analyzer 有 15 分钟总预算其中转储 12 分钟可能无法收集全部数据。总结Hang Analyzer 是 MongoDB 测试基础设施中诊断超时与挂起问题的核心工具链。从实时挂起时的信号触发SIGUSR1/SetEvent、进程筛选、core 转储与多维度信息采集C/JS 栈、锁、sessions、recovery units、存储引擎到 Evergreen 任务超时后的自动化流程、fast_archive.py的并行压缩异步上传再到core-analyzer的离线深度分析整个体系形成了在线取证 → 归档上传 → 离线分析的完整闭环。理解其进程判定规则、平台差异与各命令行参数是高效利用该工具定位 MongoDB 测试与运行时问题的前提。【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价