从应用到内核查接口超时(下)

接上文 从应用到内核查接口超时(中),查到是因为 journal 导致 write 系统调用被阻塞进而导致超时后,总感觉证据还不够充分,没有一个完美的交待。而且 leader 还想着让我把问题排查过程分享给同事们,这让我更加不安,担心搞错了方向。

在以往的博客中,我的问题结论总是确定的,如果是推论的话,我会显式注明。现在的情况让我有点犯难,推论说出去担心误导了别人,而内核层的事,我只知道基本理论,有关此问题的结论还没有。

于是,我只好再次踏上查这个问题的征程。

转载随意,文章会持续修订,请注明来源地址:https://zhenbianshu.github.io 。

打印进程内核栈

回到问题的原点,对于此问题,我能确定的资料只有稳定复现的环境和不知道什么时候会触发 write system call 延迟的 jar 包。

考虑到 write system call 被阻塞可长达几百 ms,我想我能抓出当前进程的内核栈来看一下 write system call 此时被阻塞在什么位置。

具体步骤为:

多个线程不便于抓内核栈,先将程序修改为单线程定量写入。

使用 jar 包启动一个进程,使用 ps 拿到进程号。

再通过 top -H -p pid 拿到占用 cpu、内存等资源最多的线程 ID,或使用 strace 启动,查看其输出里正在写入的线程 ID。

使用 watch 命令搭配 pstack 或 cat /proc/pid/stack 不停打印进程内核栈。具体命令为 watch -n 0.1 "date +%s >> stack.log;cat /proc/pid/stack >> stack.log"

找到 write system call 被阻塞时的时间戳,在 stack.log 里查看当时的进程内核栈。

可稳定收集到 write system call 被阻塞时,进程内核栈为:

[<ffffffff812e31f4>] call_rwsem_down_read_failed+0x14/0x30 [<ffffffffa0195854>] ext4_da_get_block_prep+0x1a4/0x4b0 [ext4] [<ffffffff811fbe17>] __block_write_begin+0x1a7/0x490 [<ffffffffa019b71c>] ext4_da_write_begin+0x15c/0x340 [ext4] [<ffffffff8115685e>] generic_file_buffered_write+0x11e/0x290 [<ffffffff811589c5>] __generic_file_aio_write+0x1d5/0x3e0 [<ffffffff81158c2d>] generic_file_aio_write+0x5d/0xc0 [<ffffffffa0190b75>] ext4_file_write+0xb5/0x460 [ext4] [<ffffffff811c64cd>] do_sync_write+0x8d/0xd0 [<ffffffff811c6c6d>] vfs_write+0xbd/0x1e0 [<ffffffff811c76b8>] SyS_write+0x58/0xb0 [<ffffffff81614a29>] system_call_fastpath+0x16/0x1b [<ffffffffffffffff>] 0xffffffffffffffff

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsssxf.html