一、现象
最近测试发现了任务卡住的问题,比较有意思,记录一下
现象简单描述下:
- 数据最终无法输出
- 通过日志发现有一个模块A任务统计长期增长,但是消费的统计长期不动,怀疑卡住了
- pstack进程,确认卡住了,如下:
1621 Thread 2 (Thread 0x7f0ac81c8700 (LWP 26481)):
1622 #0 0x00007f0ccf785d62 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
1623 #1 0x00007f0ce1d74488 in oceanbase::common::ObCond::timedwait (this=0x7f0cb43818f0, time_us=10000000) at
#2 逻辑:wait_task_ready()
....
二、排查
模块A卡住的逻辑,在等待任务完成其他操作,才能输出。因此需要排查具体哪个任务卡住,以及为什么任务没有ready等等
直接打开DEBUG或者加日志的方式,可以排查,但是日志太多,同时重新跑任务也很缓慢,如果是并发问题,还不一定能再次复现。因此用gcore debug该问题
2.1 gcore
gcore - Generate a core file of a running program
gcore顾名思义,不破坏进程,但是生成一个core文件,之后进程仍然可以进行,然后通过二进制和core文件,可以Debug内存信息
详细参考gcore
gcore -o /data/1/ pid
指定路径生成core文件
2. gdb-debug
gdb /data1/core.file
通过info threads可以查看当前进程包含所有线程,显示发现有近200个,如何定位我们关心卡住的线程?
之前通过pstack,是有这样标示的:
1621 Thread 2 (Thread 0x7f0ac81c8700 (LWP 26481)):
通过LWP 26481就可以找到对应线程ID,
attach threadID
bt
找到对应堆栈,查看内存信息,进而找到卡住的任务信息
3. 并发场景
通过上述内存信息,可以看到卡住任务详细信息,进而通过日志找到相关联的信息,发现是一个并发问题,抽象卡住时间轴如下:
时间 线程B 线程C
t1 parse数据
t2 drop本地cache
t3 判断数据是否需要过滤[查找本地cache]
数据过滤了,然后没有任务回调,从而卡住
如果是如下时间轴,就没问题:
时间 线程B 线程C
t1 parse数据
t2 判断数据是否需要过滤[查找本地cache]
数据未过滤,然后任务回调,输出
drop本地cache