Cadence集群活跃线程数持续异常偏高问题排查咨询
Cadence集群负载测试后线程数持续超4000的排查与解决
排查步骤
- 先定位线程归属
登录集群节点执行ps -eLf | grep <cadence服务名>| wc -l确认高线程是出在frontend、history、matching还是自研worker进程上,拿到对应进程PID后,执行top -H -p <PID>按线程CPU占用排序,取TOP20的线程ID。
如果是Java版本的Cadence服务,执行jstack <PID> > stack_dump.log导出全量线程栈,搜索上述线程ID对应的栈帧;如果是Go版本服务,用go tool pprof http://<服务IP>:<pprof端口>/debug/pprof/goroutine?debug=2拉取协程栈,定位线程阻塞点。排查误区:禁用sticky workflow只会关闭工作流执行实例的缓存,不会自动回收已经创建的轮询线程、RPC连接线程、后台异步任务线程,线程不会因为关了sticky配置自动下降。
- 核对高频异常点
- 查matching组件的轮询配置:核对
matchingPollMaxSize、pollerIdleTimeout两个参数,负载测试时如果压测端发起了大量轮询请求,且没有配置轮询线程空闲超时,matching为每个任务分区创建的轮询线程会永久驻留,哪怕没有流量也不会回收。 - 查history组件的异步任务队列:看传输队列、定时器队列、跨集群复制队列的任务积压计数,哪怕没有活跃工作流,如果之前压测产生的异常任务配置了无限重试、零间隔退避,会一直循环占用执行线程,不会自动退出。
- 查组件间RPC连接池配置:Cadence各服务组件之间的gRPC连接如果用了固定大小连接池,压测时扩容的连接对应的读写线程不会随流量下降自动缩容,大部分默认发行版的连接池没有开启空闲连接回收逻辑。
- 查外接worker配置:如果压测时接入了自定义决策/活动worker,核对worker端的轮询线程配置,固定大小的worker轮询池不会因为没有任务自动缩容。
- 查matching组件的轮询配置:核对
解决方案
- 轮询线程驻留场景:给所有轮询逻辑配置
pollerIdleTimeout=60s,同时设置单任务分区的最大轮询线程数上限,不要使用默认的无限制配置,空闲超过阈值的线程会被自动销毁。 - 异步任务死循环重试场景:先清理队列中卡在无限重试的异常任务,调整重试策略,配置合理的指数退避间隔和最大重试次数,避免任务空转占线程。
- 连接池不缩容场景:将固定大小gRPC连接池替换为带空闲回收的动态连接池,设置
idleConnectionTimeout=120s,流量回落后多余连接会自动释放,对应线程同步销毁。 - 自研worker配置问题:将worker端固定轮询线程池改为可伸缩的缓存线程池,设置空闲线程回收阈值,无任务时自动缩容到核心线程数。
- 临时应急:如果当前线程占用已经影响服务稳定性,可以对服务节点做滚动重启,重启后线程数会直接回落到正常基线,后续再按上述配置调整避免问题复现。
内容的提问来源于stack exchange,提问作者Ezio
相关产品推荐
相关产品推荐

