1. 程式人生 > >Linux服務端swap配置和監控

Linux服務端swap配置和監控

什麼是swap

Linux作業系統將實體記憶體分為多個小的記憶體塊,稱之為頁(pages). 當應用請求的實體記憶體不夠分配時,作業系統會將一段時間之內不用的記憶體頁交換至swap分割槽,從而為應用釋放記憶體空間。

Swap對於系統過來說非常重要:
首先,當主記憶體不夠用時,作業系統可以swap out一部分記憶體頁,迅速為當前急需記憶體的應用或者程序分配記憶體;其次,某些記憶體頁只在應用初始化階段用到,之後可能就不再使用了,作業系統可以將這些記憶體頁swap out,從而為應用或者磁碟cache騰出更多的記憶體空間。

swap有哪些缺陷

我們知道,計算機磁碟I/O通常是系統的瓶頸所在。主記憶體的讀寫速度是納秒級別,而磁碟讀寫速度是毫秒級別,兩者相差3、4個數量級。然而,即使是當前廣泛使用的SSD,讀寫速度相比主記憶體或者CPU cache也相差2、3個數量級。系統發生swap交換越多,那麼系統自然也越慢。

特別對於web伺服器來說,都是面對使用者的互動式應用,因此響應速度尤其重要。如果系統經常因為swap交換而變得響應遲鈍,那麼使用者體驗效果可想而知。

總結成一句話:swap分割槽要有,在關鍵時刻不至於讓你的應用因為記憶體不夠用而被作業系統OOM KILLER幹掉;但是不到關鍵時刻不要進行swap交換,因為這些操作會影響系統的響應速度。

人為干預Linux的swap行為——配置Swappiness

Swappiness是Linux的一個屬性,取值範圍0-100,用於控制作業系統進行swap out交換以及丟棄記憶體cache頁的傾向程度:數值越高,表示作業系統進行swap out的“積極性”越高。

簡而言之:
vm.swappiness = 0,表示只有在避免OOM的時候才進行swap操作;
vm.swappiness = 60,系統預設值;
vm.swappiness = 100,系統主動的進行swap操作。

檢視當前swappiness引數,linux系統一般預設值為60:

$ cat /proc/sys/vm/swappiness 60

修改Swappiness引數:

$ sudo echo 0 > /proc/sys/vm/swappiness

為了使上面的修改永久生效,還需要在/etc/sysctl.conf後面加上

vm.swappiness = 0

目前酒店搜尋組所屬的伺服器該引數都被配置為0.

監控伺服器swap的使用

檢視swap的整體使用情況

$ free -m
             total       used       free     shared    buffers     cached
Mem:          7836       6078       1758          0        165       3000
-/+ buffers/cache:       2911       4924
Swap:         7999          0       7999

關注最後一行就可以了,一目瞭然。

vmstat檢視swap in 和 swap out

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
1  0      0 1721436 170864 3090256    0    0    53    50  153   28  3 10 87  0  0
1  0      0 1721548 170864 3090300    0    0     0    44 7220 5693  5 11 84  0  0
1  0      0 1721424 170864 3090300    0    0     0     0 6826 5196  5 10 85  0  0

其中si和so分別代表swap in和swap out,上圖表明我的系統當前時間沒有進行swap操作。

檢視每個程序使用swap的情況

Linux系統中有一個檔案smaps檔案,記錄了當前程序所對應的記憶體映像資訊,路徑為/proc/$pid/smaps,以酒店搜尋組hslist系統的Java程序為例(只輸出一個記憶體塊映象資訊):

$ sudo cat /proc/25665/smaps | head -n9
40000000-40009000 r-xp 00000000 ca:07 1312980                            /home/q/java/jdk1.6.0_37/bin/java
Size:                36 kB
Rss:                 36 kB
Shared_Clean:        36 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:        0 kB
Swap:                 0 kB
Pss:                 11 kB

其中Swap欄位代表該記憶體塊存在於swap分割槽的資料大小,其它欄位的意思請戳這裡。

瞭解了這個就可以用指令碼統計了,以下指令碼摘自網路,直接拿來用:

#!/bin/bash

function getswap {
SUM=0
OVERALL=0for DIR in `find /proc/ -maxdepth 1 -type d | egrep "^/proc/[0-9]"` ; doPID=`echo $DIR | cut -d / -f 3`
PROGNAME=`ps -p $PID -o comm --no-headers`for SWAP in `grep Swap $DIR/smaps 2>/dev/null| awk '{ print $2 }'`dolet SUM=$SUM+$SWAP
done
echo "PID=$PID - Swap used: $SUM - ($PROGNAME )"let OVERALL=$OVERALL+$SUM
SUM=0

done
echo "Overall swap used: $OVERALL"}

getswap
#getswap|egrep -v "Swap used: 0"

執行結果:

$ getswap|egrep -v "Swap used: 0"Overall swap used: 0

當然,多數時候我們只需要關注我們的java程序是否吃swap,這就更簡單了,不需要上面那個複雜的指令碼,單行awk就搞定了:

pgrep java | xargs -I{} sudo cat /proc/{}/smaps | grep 'Swap' | awk '{a+=$(NF-1)}END{print a}'

如何清除被佔用的swap

在我們明確知道哪些程序吃swap以後,接下來的問題就是我們如何釋放這些swap,釋放swap的意思就是把交換到swap中的資料swap in到實體記憶體頁中。有兩種做法可以達到目的:

重啟吃swap的服務,比如重啟一下我們的java程序

swapoff && swapon
這個方法的好處是,不用重啟服務,但是需要確保現在有足夠的實體記憶體可以容下從swap中釋放出來的資料。下面給出了swapoff和swapon的具體做法,大家注意看swapoff後和swapon後,free的輸出有什麼異同。

可以看到swapoff後,free的輸出裡,swap分割槽的大小變為0,佔用變為0,也就是說swap分割槽中的資料已經釋放到實體記憶體中,同時swap分割槽被禁用。swapon後,free的輸出裡,swap分割槽的容量又恢復為4094M,也就是說swap分割槽重新被啟用了。當然我們可以把這兩個命令寫到一起:

sudo /sbin/swapoff -a && sudo /sbin/swapon -a

參考文獻

http://www.data-recovery-app.com/datarecovery/linux-swap.html
http://arminds.com/forums/linux-talk/226-configure-linux-swap-to-improve-server-performance
http://en.wikipedia.org/wiki/Swappiness