日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)

發布時間:2024/9/3 windows 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節,我用一個 Nginx+PHP 的案例,給你講了服務器 CPU 使用率高的分析和應對方法。這里你一定要記得,當碰到無法解釋的 CPU 使用率問題時,先要檢查一下是不是短時應用在搗鬼。短時應用的運行時間比較短,很難在 top 或者 ps 這類展示系統概要和進程快照的工具中發現,你需要使用記錄事件的工具來配合診斷,比如 execsnoop 或者 perf top。這些思路你不用刻意去背,多練習幾次,多在操作中思考,你便能靈活運用。另外,我們還講到 CPU 使用率的類型。除了上一節提到的用戶 CPU 之外,它還包括系統 CPU(比如上下文切換)、等待 I/O 的 CPU(比如等待磁盤的響應)以及中斷 CPU(包括軟中斷和硬中斷)等。我們已經在上下文切換的文章中,一起分析了系統 CPU 使用率高的問題,剩下的等待 I/O 的 CPU 使用率(以下簡稱為 iowait)升高,也是最常見的一個服務器性能問題。今天我們就來看一個多進程 I/O 的案例,并分析這種情況。

進程狀態

當 iowait 升高時,進程很可能因為得不到硬件的響應,而長時間處于不可中斷狀態。從 ps 或者 top 命令的輸出中,你可以發現它們都處于 D 狀態,也就是不可中斷狀態(Uninterruptible Sleep)。既然說到了進程的狀態,進程有哪些狀態你還記得嗎?我們先來回顧一下。top 和 ps 是最常用的查看進程狀態的工具,我們就從 top 的輸出開始。下面是一個 top 命令輸出的示例,S 列(也就是 Status 列)表示進程的狀態。從這個示例里,你可以看到 R、D、Z、S、I 等幾個狀態,它們分別是什么意思呢?$ topPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 28961 root 20 0 43816 3148 4040 R 3.2 0.0 0:00.01 top620 root 20 0 37280 33676 908 D 0.3 0.4 0:00.01 app1 root 20 0 160072 9416 6752 S 0.0 0.1 0:37.64 systemd1896 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 devapp2 root 20 0 0 0 0 S 0.0 0.0 0:00.10 kthreadd4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq7 root 20 0 0 0 0 S 0.0 0.0 0:06.37 ksoftirqd/0我們挨個來看一下:
  • R 是 Running 或 Runnable 的縮寫,表示進程在 CPU 的就緒隊列中,正在運行或者正在等待運行。
  • D 是 Disk Sleep 的縮寫,也就是不可中斷狀態睡眠(Uninterruptible Sleep),一般表示進程正在跟硬件交互,并且交互過程不允許被其他進程或中斷打斷。
  • Z 是 Zombie 的縮寫,如果你玩過“植物大戰僵尸”這款游戲,應該知道它的意思。它表示僵尸進程,也就是進程實際上已經結束了,但是父進程還沒有回收它的資源(比如進程的描述符、PID 等)。
  • S 是 Interruptible Sleep 的縮寫,也就是可中斷狀態睡眠,表示進程因為等待某個事件而被系統掛起。當進程等待的事件發生時,它會被喚醒并進入 R 狀態。
  • I 是 Idle 的縮寫,也就是空閑狀態,用在不可中斷睡眠的內核線程上。前面說了,硬件交互導致的不可中斷進程用 D 表示,但對某些內核線程來說,它們有可能實際上并沒有任何負載,用 Idle 正是為了區分這種情況。要注意,D 狀態的進程會導致平均負載升高, I 狀態的進程卻不會。
當然了,上面的示例并沒有包括進程的所有狀態。除了以上 5 個狀態,進程還包括下面這 2 個狀態。第一個是 T 或者 t,也就是 Stopped 或 Traced 的縮寫,表示進程處于暫停或者跟蹤狀態。向一個進程發送 SIGSTOP 信號,它就會因響應這個信號變成暫停狀態(Stopped);再向它發送 SIGCONT 信號,進程又會恢復運行(如果進程是終端里直接啟動的,則需要你用 fg 命令,恢復到前臺運行)。而當你用調試器(如 gdb)調試一個進程時,在使用斷點中斷進程后,進程就會變成跟蹤狀態,這其實也是一種特殊的暫停狀態,只不過你可以用調試器來跟蹤并按需要控制進程的運行。另一個是 X,也就是 Dead 的縮寫,表示進程已經消亡,所以你不會在 top 或者 ps 命令中看到它。了解了這些,我們再回到今天的主題。先看不可中斷狀態,這其實是為了保證進程數據與硬件狀態一致,并且正常情況下,不可中斷狀態在很短時間內就會結束。所以,短時的不可中斷狀態進程,我們一般可以忽略。但如果系統或硬件發生了故障,進程可能會在不可中斷狀態保持很久,甚至導致系統中出現大量不可中斷進程。這時,你就得注意下,系統是不是出現了 I/O 等性能問題。再看僵尸進程,這是多進程應用很容易碰到的問題。正常情況下,當一個進程創建了子進程后,它應該通過系統調用 wait() 或者 waitpid() 等待子進程結束,回收子進程的資源;而子進程在結束時,會向它的父進程發送 SIGCHLD 信號,所以,父進程還可以注冊 SIGCHLD 信號的處理函數,異步回收資源。如果父進程沒這么做,或是子進程執行太快,父進程還沒來得及處理子進程狀態,子進程就已經提前退出,那這時的子進程就會變成僵尸進程。換句話說,父親應該一直對兒子負責,善始善終,如果不作為或者跟不上,都會導致“問題少年”的出現。通常,僵尸進程持續的時間都比較短,在父進程回收它的資源后就會消亡;或者在父進程退出后,由 init 進程回收后也會消亡。一旦父進程沒有處理子進程的終止,還一直保持運行狀態,那么子進程就會一直處于僵尸狀態。大量的僵尸進程會用盡 PID 進程號,導致新進程不能創建,所以這種情況一定要避免。

案例分析

接下來,我將用一個多進程應用的案例,帶你分析大量不可中斷狀態和僵尸狀態進程的問題。這個應用基于 C 開發,由于它的編譯和運行步驟比較麻煩,我把它打包成了一個 Docker 鏡像。這樣,你只需要運行一個 Docker 容器就可以得到模擬環境。

你的準備

下面的案例仍然基于 Ubuntu 18.04,同樣適用于其他的 Linux 系統。我使用的案例環境如下所示:機器配置:2 CPU,8GB 內存預先安裝 docker、sysstat、dstat 等工具,如 apt install docker.io dstat sysstat這里,dstat 是一個新的性能工具,它吸收了 vmstat、iostat、ifstat 等幾種工具的優點,可以同時觀察系統的 CPU、磁盤 I/O、網絡以及內存使用情況。接下來,我們打開一個終端,SSH 登錄到機器上,并安裝上述工具。注意,以下所有命令都默認以 root 用戶運行,如果你用普通用戶身份登陸系統,請運行 sudo su root 命令切換到 root 用戶。如果安裝過程有問題,你可以先上網搜索解決,實在解決不了的,記得在留言區向我提問。溫馨提示:案例應用的核心代碼邏輯比較簡單,你可能一眼就能看出問題,但實際生產環境中的源碼就復雜多了。所以,我依舊建議,操作之前別看源碼,避免先入為主,而要把它當成一個黑盒來分析,這樣你可以更好地根據現象分析問題。你姑且當成你工作中的一次演練,這樣效果更佳。

操作和分析

安裝完成后,我們首先執行下面的命令運行案例應用:$ docker run --privileged --name=app -itd feisky/app:iowait然后,輸入 ps 命令,確認案例應用已正常啟動。如果一切正常,你應該可以看到如下所示的輸出:$ ps aux | grep /app root 4009 0.0 0.0 4376 1008 pts/0 Ss+ 05:51 0:00 /app root 4287 0.6 0.4 37280 33660 pts/0 D+ 05:54 0:00 /app root 4288 0.6 0.4 37280 33668 pts/0 D+ 05:54 0:00 /app從這個界面,我們可以發現多個 app 進程已經啟動,并且它們的狀態分別是 Ss+ 和 D+。其中,S 表示可中斷睡眠狀態,D 表示不可中斷睡眠狀態,我們在前面剛學過,那后面的 s 和 + 是什么意思呢?不知道也沒關系,查一下 man ps 就可以。現在記住,s 表示這個進程是一個會話的領導進程,而 + 表示前臺進程組。這里又出現了兩個新概念,進程組和會話。它們用來管理一組相互關聯的進程,意思其實很好理解。進程組表示一組相互關聯的進程,比如每個子進程都是父進程所在組的成員;而會話是指共享同一個控制終端的一個或多個進程組。比如,我們通過 SSH 登錄服務器,就會打開一個控制終端(TTY),這個控制終端就對應一個會話。而我們在終端中運行的命令以及它們的子進程,就構成了一個個的進程組,其中,在后臺運行的命令,構成后臺進程組;在前臺運行的命令,構成前臺進程組。明白了這些,我們再用 top 看一下系統的資源使用情況:# 按下數字 1 切換到所有 CPU 的使用情況,觀察一會兒按 Ctrl+C 結束 $ top top - 05:56:23 up 17 days, 16:45, 2 users, load average: 2.00, 1.68, 1.39 Tasks: 247 total, 1 running, 79 sleeping, 0 stopped, 115 zombie %Cpu0 : 0.0 us, 0.7 sy, 0.0 ni, 38.9 id, 60.5 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.7 sy, 0.0 ni, 4.7 id, 94.6 wa, 0.0 hi, 0.0 si, 0.0 st ...PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND4340 root 20 0 44676 4048 3432 R 0.3 0.0 0:00.05 top4345 root 20 0 37280 33624 860 D 0.3 0.0 0:00.01 app4344 root 20 0 37280 33624 860 D 0.3 0.4 0:00.01 app1 root 20 0 160072 9416 6752 S 0.0 0.1 0:38.59 systemd ...從這里你能看出什么問題嗎?細心一點,逐行觀察,別放過任何一個地方。忘了哪行參數意思的話,也要及時返回去復習。好的,如果你已經有了答案,那就繼續往下走,看看跟我找的問題是否一樣。這里,我發現了四個可疑的地方。先看第一行的平均負載( Load Average),過去 1 分鐘、5 分鐘和 15 分鐘內的平均負載在依次減小,說明平均負載正在升高;而 1 分鐘內的平均負載已經達到系統的 CPU 個數,說明系統很可能已經有了性能瓶頸。再看第二行的 Tasks,有 1 個正在運行的進程,但僵尸進程比較多,而且還在不停增加,說明有子進程在退出時沒被清理。接下來看兩個 CPU 的使用率情況,用戶 CPU 和系統 CPU 都不高,但 iowait 分別是 60.5% 和 94.6%,好像有點兒不正常。最后再看每個進程的情況, CPU 使用率最高的進程只有 0.3%,看起來并不高;但有兩個進程處于 D 狀態,它們可能在等待 I/O,但光憑這里并不能確定是它們導致了 iowait 升高。我們把這四個問題再匯總一下,就可以得到很明確的兩點:
  • 第一點,iowait 太高了,導致系統的平均負載升高,甚至達到了系統 CPU 的個數。
  • 第二點,僵尸進程在不斷增多,說明有程序沒能正確清理子進程的資源。
那么,碰到這兩個問題該怎么辦呢?結合我們前面分析問題的思路,你先自己想想,動手試試,下節課我來繼續“分解”。

小結

今天我們主要通過簡單的操作,熟悉了幾個必備的進程狀態。用我們最熟悉的 ps 或者 top ,可以查看進程的狀態,這些狀態包括運行(R)、空閑(I)、不可中斷睡眠(D)、可中斷睡眠(S)、僵尸(Z)以及暫停(T)等。其中,不可中斷狀態和僵尸狀態,是我們今天學習的重點。
  • 不可中斷狀態,表示進程正在跟硬件交互,為了保護進程數據和硬件的一致性,系統不允許其他進程或中斷打斷這個進程。進程長時間處于不可中斷狀態,通常表示系統有 I/O 性能問題。
  • 僵尸進程表示進程已經退出,但它的父進程還沒有回收子進程占用的資源。短暫的僵尸狀態我們通常不必理會,但進程長時間處于僵尸狀態,就應該注意了,可能有應用程序沒有正常處理子進程的退出。

思考

最后,我想請你思考一下今天的課后題,案例中發現的這兩個問題,你會怎么分析呢?又應該怎么解決呢?你可以結合前面我們做過的案例分析,總結自己的思路,提出自己的問題。

總結

以上是生活随笔為你收集整理的07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。