系統監控是運維工作中重要的一環,本文以 atop 工具為例來介紹系統的重要監控項。
atop可以使用yum或apt包管理器進行安裝。atop man page 中詳細說明了 atop 中各監控項含義及atop命令用法。
如上圖所示, atop 的界面分為上半部分的系統監控項和下半部分的進程列表。
atop 每10s更新一次系統監控項以及在這段時間內狀態發生變化的進程,按下A鍵可以查看全部進程。
系統狀態
進程
第一行PRC顯示總體進程狀況:
- sys, user 表示 CPU 在內核態和用戶態的運行時間比例
#proc
為當前總進程數,#trun
表示 running 狀態線程數#tslpi
表示 sleeping interruptible 狀態的進線程數#tslpu
表示 sleeping uninterruptible 狀態線程數#zombie
表示僵屍進程數
- clones 表示在監控周期(默認10s)內 clone() 系統調用次數
linux 中進程有兩種 sleep 狀態:
- interruptible sleep: 進程接收系統信號,可以被系統信號中斷
- uninterruptible sleep: 進程不接收系統信號,不可被系統信號中斷,包括kill -9 (SIGKILL 信號)。當一個進程向磁盤讀寫數據時,為了保證數據的一致性,在得到磁盤回復前,它是不能被其他進程或者中斷打斷的,這個時候的進程就處於不可中斷狀態。
一個進程使用fork創建子進程,如果子進程退出,而父進程並沒有調用wait或waitpid獲取子進程的狀態信息,那么子進程的進程描述符仍然保存在系統中,這種進程稱之為僵屍進程。大量僵屍進程可能會占用進程描述符空間導致無法創建進程。
孤兒進程是容易與僵屍進程混淆的一類進程,孤兒進程是父進程終止的進程,它們會被 init 進程接管並不會產生危害。
CPU
在 atop 中每個 CPU 邏輯核心擁有一個 cpu
行表示自身狀態, 最前面的 CPU 行則展示系統總覽。
- sys 表示CPU在內核態工作時間比例
- user 表示 CPU 在用戶態工作時間比例
- irq 表示 CPU 處理系統中斷所消耗的時間比例
- idle 表示 CPU 空閑時間比例
CPL 行表示 CPU 負載(CPU Load):
- avg1, avg5, avg15: 過去 1min、5min和 15min 內的平均系統負載
- csw 表示監控周期內上下文切換的次數
- intr 表示監控周期內中斷發生的次數
系統負載
CPU 負載或稱為系統負載是一個容易被誤解的監控項,它的定義為內核運行隊列中 running 或 uninterruptible sleep 狀態的進程的平均數與CPU計算能力的比值。
系統負載 1.0 說明CPU恰好滿載,當系統負載大於1.0時會有進程因為等待CPU而阻塞。在多核系統中,系統負載等於CPU核心數表示恰好滿載,如在上圖所示雙核系統中,load=2說明恰好滿載。
上文已經說明,uninterruptible sleep 進程通常是在等待IO, 當網絡異常或磁盤故障時會導致大量進程處於 uninterruptible sleep 狀態從而導致 Load 急劇上升。
常見的服務器程序大多數為IO密集型程序,常見的CPU密集型任務包括:
- 大規模的排序計算, 如 mysql filesort
- 大量的正則表達式匹配
- 大量的 Hash Code 計算
- 大規模的加解密或壓縮解壓計算
當我們發現 CPU 使用率上升時,我們可以優先考慮是否在上述CPU密集型任務。
內存
MEM 行描述內存使用情況:
- tot: 物理內存總量
- free: 空閑內存總量
- cache: 文件緩存用量
- buff: 塊設備緩存用量
- slab: 系統內核 slab 內存用量
- dirty: 需要寫回磁盤的臟頁用量,這部分內存使用已包含在cache中
這里出現了兩個兩個緩存: cache 和 buffer:
cache 是指 page cache, 是在文件系統級別的緩存。用於緩存從文件中讀取的數據,下次讀取文件時可以從內存中快速獲取,不需要進行磁盤IO。
buffer 是磁盤等塊設備的緩存,不經過文件系統直接對磁盤進行讀寫的數據會緩存在 buffer 中。
文件需要映射到物理磁盤的塊上,這層映射關系由文件系統負責維護。沒有文件系統支持的數據讀寫都會使用 buffer 緩存,比如文件系統元數據的緩存,以及 dd 等工具直接對磁盤進行讀寫時需要的緩存。
cache 和 buffer 兩個緩存既會被用在讀請求中,也會被用在寫請求中。
PAG 行表示頁緩存的使用情況:
- scan: 當可用內存不足時掃描的頁數,這個值過高說明可用內存不足
- stall: 內核緊急將頁加載到內存中的次數,這個值過高說明可用內存不足
- steal: 虛擬機相關指標
- swin: 從 Swap 分區將頁加載到內存的次數
- swout: 將內存頁寫入 Swap 分區的次數
scan 和 steal 的解釋比較難理解,附上 man page 中的原文:
This line contains the number of scanned pages ('scan') due to the fact that free memory drops below a particular threshold and the number times that the kernel tries to reclaim pages due to an urgent need ('stall')
SWP 行表示 Swap 分區使用狀態:
- tot: Swap 分區總大小
- free: Swap 分區空閑空間大小
當物理內存不足時,內核會將進程內存中不常用的頁逐出內存寫入磁盤中的 Swap 分區,當進程需要讀取這些頁時再將它們從磁盤中加載到內存。
磁盤
DSK 列描述磁盤使用情況:
- vda: 該列為磁盤設備名,每個設備擁有一行
- busy: 設備處理IO請求的時間占比
- read: 監控周期內讀請求數
- write: 監控周期內寫請求數
- KiB/r: 每次讀請求的平均數據量
- KiB/w: 每次寫請求的平均數據量
- MBr/s: 每秒讀取的數據量
- MBw/s: 每秒寫入的數據量
- avq: io 隊列的平均長度
- avio: 單次讀寫請求需要的毫秒數
網絡
網絡層通常包含 transport、network、 eth 和 lo 行, 分別表示傳輸層、網絡層、以太網(數據鏈路層)和本地回環的監控指標。
- tcpi/udpi/ipi: 接收的 tcp/udp/ip 數據包
- tcpo/udpo/ipo : 發出的 tcp/udp/ip 數據包
- tcpao: 主動建立的tcp連接數(active open)
- tcppo: 被動建立的tcp連接數(passive open), 即通過 listen() 建立的連接數
- tcprs: tcp 重傳次數
- tcpie: 讀取時發生錯誤的次數
進程列表
進程列表有多個視圖分別展示不同方面的數據:
- 默認視圖(Generic information): 按G鍵回到默認視圖
- 內存視圖(Memory information): 按M鍵進入內存視圖,顯示進程的內存占用情況
- 命令行視圖(Command Line information): 按C鍵進入命令行視圖,顯示進程啟動時詳細命令行參數
- 調度器視圖(Scheduling information): 按S鍵進入視圖,顯示線程調度、CPU使用和運行統計
- 磁盤視圖(Disk information): 按D鍵進入視圖,顯示進程的磁盤IO使用情況
- 網絡視圖(Network information): 按N鍵進入視圖,顯示進程的網絡IO使用情況
atop 默認展示過去10s內狀態發生變化的進程,按下A鍵可以查看全部進程。
默認視圖
默認視圖展示常用的監控項:
- PID: 進程ID
- SYSCPU: 在內核態下使用CPU時間
- USERCPU: 在用戶態下使用CPU時間
- VGROW: 過去一個監控周期內進程的虛擬內存空間增長,包括malloc()分配內存、使用共享內存以及free()釋放內存造成的空間變化
- RGROW: 過去一個監控周期內進程常駐內存空間(resident memory)增長, 即進程內存空間中駐留在物理內存中未被逐出到SWAP分區的部分。
- RUID, EUID, SUID: 啟動進程的UID
- RUID: 登錄時的用戶ID
- EUID: Effective Uid。通常EUID=RUID, setuid 或 sudo 等指令能以另一個用戶身份執行命令,這個被“代理”的用戶即為 Effective User。
- EXC: 進程退出時的返回碼
- THR: 進程中的線程數
- S: 進程狀態,與ps命令的進程描述符相同
簡單介紹一下進程狀態
- R: Runing
- S: sleeping interruptible 等待某個事件
- D: sleeping non-interruptible 通常在等待IO
- Z: Zombie 僵屍進程
- E: 進程在上個監控周期內退出
- T: TASK_STOPPED 或 TASK_TRACED 狀態
- TASK_STOPPED: 進程收到 SIGSTOP 信號進入暫停狀態
- TASK_TRACED: 進程進入暫停狀態等待跟蹤它的進程,比如進程被 gdb 的斷點暫停
內存視圖
按M鍵可以進入內存視圖查看進程的內存使用情況:
- MINFLT: 進程缺頁小錯誤(minor page fault)的次數
- MAJFLT: 進程缺頁大錯誤(major page fault)的次數
- VSIZE: 虛擬內存空間的總大小
- RSIZE: 常駐內存(resident memory)的總大小
- VGROW: 虛擬內存空間在上個監控周期的增長
- RGROW: 虛擬內存空間在上個監控周期的增長
- MEM: 物理內存使用占比
在 Linux 的內存管理系統中需要讀取磁盤才能解決缺頁中斷稱為大錯誤(Major Page Fault), 不需要讀取磁盤可以解決的缺頁中斷被稱為小錯誤(Minor Page Fault)。
一般情況下 MINFLT 是因為頻繁分配/回收大內存塊導致的,可以考慮使用內存池優化程序來減少缺頁錯誤; MAJFLT 是由於物理內存不足導致。
調度視圖
按S鍵可以進入調度視圖(Scheduling View)查看進程運行和CPU情況:
- TRUN: running 狀態的線程數
- TSLPI: sleeping interruptible 狀態線程數
- TSLPU: 表示 sleeping uninterruptible 狀態進程數
- PILI: 調度策略
- PRI,NICE: 優先級,PRI+NICE越低優先級越高
- CPU: CPU 使用時間占比
監控服務
除了查看當前的狀態外,atop 還可以服務方式運行在后台監控並記錄系統狀態。
使用 service atop start
或 systemctl start atop
命令啟動atop監控服務。
atop 默認將數據保存在/var/log/atop
目錄下,10 分鍾采集一次,保留最近28天的數據。上述配置可以在 /etc/atop/atop.daily
文件中進行修改。
使用 atop -r <filename>
命令讀取日志文件。按t鍵向前翻頁,T鍵向后翻頁,b鍵跳轉到指定時間,時間格式為hh:mm。