情景:測試人員在進行 RabbitMQ 服務器問題排查時,進行了各類重啓操做,以後忽然發現機器變的很卡。
排查過程:
1. 經過 top 查看,發現名爲 sa 的進程 CPU 佔用率幾乎 100% 。
2. 查看 sa 進程中哪一個線程佔用 CPU 比較高nginx
[root@rmq_2 ~]# top -Hp 1362 top - 05:36:26 up 2 days, 3:08, 2 users, load average: 1.77, 3.69, 5.11 Tasks: 16 total, 0 running, 16 sleeping, 0 stopped, 0 zombie Cpu0 : 0.4%us, 2.8%sy, 0.0%ni, 95.7%id, 0.0%wa, 1.1%hi, 0.0%si, 0.0%st Cpu1 : 0.4%us, 14.7%sy, 0.0%ni, 29.4%id, 53.8%wa, 0.0%hi, 1.8%si, 0.0%st Cpu2 : 0.7%us, 2.1%sy, 0.0%ni, 95.9%id, 0.0%wa, 0.0%hi, 1.4%si, 0.0%st Cpu3 : 0.3%us, 5.8%sy, 0.0%ni, 77.1%id, 16.4%wa, 0.0%hi, 0.3%si, 0.0%st Mem: 3924376k total, 3775972k used, 148404k free, 143432k buffers Swap: 2097144k total, 688428k used, 1408716k free, 883568k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1532 root 20 0 83964 37m 1196 D 94.7 1.0 127:59.46 MQProducerTask 1497 root 20 0 83964 37m 1196 S 0.3 1.0 3:22.10 OspTimerTask 1362 root 20 0 83964 37m 1196 S 0.0 1.0 0:03.41 sa 1495 root 20 0 83964 37m 1196 S 0.0 1.0 0:42.97 OspLogTask 1496 root 20 0 83964 37m 1196 S 0.0 1.0 0:00.00 OspDispatchTask 1498 root 20 0 83964 37m 1196 S 0.0 1.0 0:00.14 OspTeleDaemon 1499 root 20 0 83964 37m 1196 S 0.0 1.0 0:00.00 OspPostDaemon 1500 root 20 0 83964 37m 1196 S 0.0 1.0 0:05.18 OspNodeMan 1501 root 20 0 83964 37m 1196 S 0.0 1.0 0:06.28 WDClient 1504 root 20 0 83964 37m 1196 S 0.0 1.0 0:00.00 ModuleInst 1505 root 20 0 83964 37m 1196 S 0.0 1.0 0:01.79 LgsInst 1506 root 20 0 83964 37m 1196 S 0.0 1.0 0:19.88 BmcInst 1507 root 20 0 83964 37m 1196 S 0.0 1.0 9:04.17 LogicSrvInst 1508 root 20 0 83964 37m 1196 S 0.0 1.0 0:00.00 FileSend 1531 root 20 0 83964 37m 1196 S 0.0 1.0 0:07.58 MQProducerTask 1533 root 20 0 83964 37m 1196 S 0.0 1.0 0:38.01 MQConsumerTask
從上面的信息中能夠發現兩點:服務器
3.跟蹤 MQProducerTask 線程的執行網絡
[root@rmq_2 guard]# strace -p 1532 Process 1532 attached - interrupt to quit [ Process PID=1532 runs in 32 bit mode. ] write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) write(2, "[MQ][producer_tag s:52][fsm:conn"..., 75) = -1 ENOSPC (No space left on device) ...
發現該線程一直在向 stderr 輸出打印信息,而且已經出現磁盤空間不足的提示信息。
4.確認磁盤狀況確實已滿app
[root@rmq_2 guard]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/VolGroup-LogVol01 195G 195G 0 100% / tmpfs 1.9G 0 1.9G 0% /dev/shm /dev/sda1 194M 34M 150M 19% /boot [root@rmq_2 guard]#
從業務開發瞭解到,sa 進程爲排查問題,會將 stderr 重定向到 log/sa_rabbitmq.log 日誌中。經確認, 該文件已經達到 110G+ 。
5.測試人員手動刪除 sa_rabbitmq.log 文件,可是問題依然沒有獲得解決。能夠看到磁盤佔用仍舊是 100% ,而後查看 log 下的文件,卻發現日誌大小爲 0 。測試
[root@rmq_2 log]# ll total 192472 -rw-r--r-- 1 root root 5243673 May 21 15:30 0sa.txt -rw-r--r-- 1 root root 5243277 May 21 23:44 10sa.txt -rw-r--r-- 1 root root 5243373 May 22 00:33 11sa.txt -rw-r--r-- 1 root root 5243704 May 22 01:22 12sa.txt -rw-r--r-- 1 root root 5243609 May 22 02:28 13sa.txt -rw-r--r-- 1 root root 4714496 May 22 03:35 14sa.txt -rw-r--r-- 1 root root 28672 May 22 04:42 15sa.txt -rw-r--r-- 1 root root 12288 May 22 05:26 16sa.txt -rw-r--r-- 1 root root 155648 May 22 05:27 17sa.txt -rw-r--r-- 1 root root 135168 May 22 05:27 18sa.txt -rw-r--r-- 1 root root 114688 May 22 05:32 19sa.txt -rw-r--r-- 1 root root 5243431 May 21 16:20 1sa.txt -rw-r--r-- 1 root root 5243711 May 21 17:09 2sa.txt -rw-r--r-- 1 root root 5243431 May 21 17:58 3sa.txt -rw-r--r-- 1 root root 5243278 May 21 18:48 4sa.txt -rw-r--r-- 1 root root 5243285 May 21 19:37 5sa.txt -rw-r--r-- 1 root root 5243698 May 21 20:26 6sa.txt -rw-r--r-- 1 root root 5243573 May 21 21:16 7sa.txt -rw-r--r-- 1 root root 5243399 May 21 22:05 8sa.txt -rw-r--r-- 1 root root 5243647 May 21 22:54 9sa.txt -rw-r--r-- 1 root root 118338715 May 22 01:30 daemon.log -rw-r--r-- 1 root root 38613 May 22 01:26 saexc.log -rw-r--r-- 1 root root 7099 May 22 01:26 saexc.log-maps -rw-r--r-- 1 root root 0 May 22 02:54 sa_rabbitmq.log -rw-r--r-- 1 root root 16384 May 22 05:46 sa.txt -rw-r--r-- 1 root root 8019 May 20 02:28 startsrv.log [root@rmq_2 log]#
查看網上相關資料,結論就是: 磁盤文件雖然被刪除,卻仍被某進程佔用,而且還在寫(這個說法其實不許確,由於磁盤已滿狀況下,是沒法寫入的)。在這種狀況下,經過 du 命令是沒法找到佔用磁盤的大文件。與此同時,被刪除的文件仍然會佔用磁盤空間。
6.經過命令確認被刪除的文件仍在被進程使用ui
[root@rmq_2 log]# lsof | grep deleted sa 1362 root 2w REG 253,0 197264424960 1312057 /opt/mcu/guard/log/sa_rabbitmq.log (deleted) ... [root@rmq_2 log]#
確實文件被刪除了,但仍舊被進程 sa 所佔用,解決辦法就是把相關的進程進行重啓,空間天然就被釋放了。
至於上面業務線程狂刷打印問題的緣由和解決辦法以下:
分析 MQProducerTask 線程狂刷上面的日誌信息的緣由,是由於 FSM 在 conn_idle 狀態收到了非 EV_TIMEOUT 事件。而且代碼中沒有對這個錯誤分支作事件相關處理,只是輸出打印信息。故代碼執行完畢後會從新進入 conn_idle 狀態,並沿用前一次的事件,致使死循環。源代碼以下spa
default: fprintf( stderr, "[MQ][%s s:%d][fsm:conn_idle][*] Weird! NOT Trigger by EV_TIMEOUT\n", conn->tag, amqp_get_sockfd(conn) ); break;
變動以下線程
default: fprintf( stderr, "[MQ][%s s:%d][fsm:conn_idle][*] Weird! NOT Trigger by EV_TIMEOUT, but by %d\n", conn->tag, amqp_get_sockfd(conn), trigger_ev ); update_event( conn, 0, RET_IMMEDIATELY ); conn_set_state( conn, conn_idle ); stop = 1; break;
另外,還能夠將代碼中全部要跳轉到 conn_idle 狀態,且事件更新 XXX 不爲 0 的地方都進行修改,以完全杜絕其它事件的干擾。日誌
update_event( conn, XXX, RET_IMMEDIATELY ); conn_set_state( conn, conn_idle );
補充:code
進程爲何會被置於 uninterruptible sleep 狀態呢? 處於 uninterruptible sleep 狀態的進程一般是在等待 I/O,好比磁盤 I/O,網絡 I/O,其餘外設 I/O,若是進程正在等待的 I/O 在較長的時間內都沒有響應,那麼就會很不幸地被 ps 所看到(或者經過 top 看到)。 出現這個狀態就意味着極可能有 I/O 出了問題,可能的本來包括但不限於外設自己故障,磁盤寫滿,掛載的遠程文件系統已經不可訪問等緣由。