【運維小分享】linux性能分析及調優

第一節:cpu 性能瓶頸 

計算機中,cpu是最重要的一個子系統,負責所有計算任務;基於摩爾定律的發展,cpu是發展最快的一個硬件,所以瓶頸很少出現在cpu上;我們線上環境的cpu都是多核的,並且基於SMP(symmetric multiprocessing)結構的。通過觀察線上機器cpu使用率會發現,使用率很低很低,不到5%; 說明我們的資源浪費情況多麼嚴重啊;(但爲什麼不能一臺機器多部署幾個應用呢,後邊我會解釋); 我們線上的cpu一個核支持超級線程,也就是一個核上可以並行運行幾個線程)。

機器CPU使用情況監控:

1、良好狀態指標

CPU利用率:User Time <= 70%,System Time <= 35%,User Time + System Time <= 70%。上下文切換:與CPU利用率相關聯,如果CPU利用率狀態良好,大量的上下文切換也是可以接受的。

可運行隊列:每個處理器的可運行隊列<=3個線程。

2、監控工具   vmstat

$ 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

14 0 140 2904316 341912 3952308 0 0 0 460 1106 9593 36 64 1 0 0

17 0 140 2903492 341912 3951780 0 0 0 0 1037 9614 35 65 1 0 0

20 0 140 2902016 341912 3952000 0 0 0 0 1046 9739 35 64 1 0 0

17 0 140 2903904 341912 3951888 0 0 0 76 1044 9879 37 63 0 0 0

16 0 140 2904580 341912 3952108 0 0 0 0 1055 9808 34 65 1 0 0

重要參數:

r, run queue, 可運行隊列的線程數,這些線程都是可運行狀態,只不過CPU暫時不可用

一般要求小於CPU*3的數量。

cat   /proc/stat   #可以看到有幾個CPU

b被blocked的進程數,正在等待IO請求;

in,interrupts,被處理過的中斷數

cs,context switch,系統上正在做上下文切換的數目

us,用戶佔用CPU的百分比

sys,內核和中斷佔用CPU的百分比

id,CPU完全空閒的百分比

上例可得:

sy高us低,以及高頻度的上下文切換(cs),說明應用程序進行了大量的系統調用;

這臺4核機器的r應該在12個以內,現在r在14個線程以上,此時CPU負荷很重。

一般我們認爲,如果是4核機器,r高於8是,應該就是負載很高了。

可調優性能參數:

1、 通過調整進程優先級調整 nice 命令來調整進程優先級別;可調範圍(-20到 19) 如: renice 5 pid

2、 通過調整cpu的親和度來集中處理某一箇中斷類型:(比如網卡中斷)

將系統發出的中斷都綁定在一個cpu上,這樣其他cpu繼續執行自己正在執行的線程,不被中斷打擾,從而較少了線程上下文切換時間,增強性能;

注: cpu親和度的概念: 在多核cpu中,linux操作系統搶佔式調度系統,按照cpu時間片/中斷/等不斷調度進程給cpu去執行的;

如果在一個時間片調度線程1在cpu1上運行,另外一個時間片調度線程1在cpu2上去運行,這樣會造成線程執行速度慢,性能降低。

爲什麼呢?

我們知道SMP上多核都是共享L1 ,L2 CPU Cache的。並且各個核的內存空間都是不可共享的,一個線程如果多次時間片上在不同的cpu上運行,會造成cache的不斷失效和寫入,性能會降低;

而linux的進程調度有個親和度算法可以將盡量將進程每次都調度到同一個cpu上處理;

linux調度時當然也有Loadbalance算法保證進程調度的均勻負載的;

例如: echo 03 > /proc/irq/19/smp-affinity (將中斷類型爲19的中斷綁定到第三個cpu上處理)

 

第二節:內存性能瓶頸 

首先,linux的內存管理是聰明和智能的;

linux通過(virtual memory manage)來管理內存的; 對於大多數應用,linux是不直接寫到硬盤上去的,而是先寫到 virtual memory manage 管理的文件系統緩存(也在內存中的)裏 ,方便應用的後續的讀請求;因爲和磁盤的I/O操作是昂貴的;linux會根據一些算法策略適當的時候同步到硬盤的;這就是爲什麼我們運行linux一段時間後,發現可用內存那麼少的原因,多數被cache+buffer佔用咧;

所以我們提高性能的辦法就是減少寫到磁盤的次數,提高每次寫磁盤時的效率質量;    

機器內存使用情況監控:

1、良好狀態指標

swap in (si) == 0,swap out (so) == 0

應用程序可用內存/系統物理內存 <= 70%

2、監控工具    vmstat

$ 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

0 3 252696 2432 268 7148 3604 2368 3608 2372 288 288 0 0 21 78 1

0 2 253484 2216 228 7104 5368 2976 5372 3036 930 519 0 0 0 100 0

0 1 259252 2616 128 6148 19784 18712 19784 18712 3821 1853 0 1 3 95 1

1 2 260008 2188 144 6824 11824 2584 12664 2584 1347 1174 14 0 0 86 0

2 1 262140 2964 128 5852 24912 17304 24952 17304 4737 2341 86 10 0 0 4

重要參數:

swpd,    已使用的 SWAP 空間大小,KB 爲單位;

free,      可用的物理內存大小,KB 爲單位;

buff,       物理內存用來緩存讀寫操作的buffer大小,KB 爲單位;

cache,   物理內存用來緩存進程地址空間的 cache 大小,KB 爲單位;

si,          數據從 SWAP 讀取到 RAM(swap in)的大小,KB 爲單位;

so,         數據從 RAM 寫到 SWAP(swap out)的大小,KB 爲單位。

上例可得:

物理可用內存 free 基本沒什麼顯著變化,swapd逐步增加,說明最小可用的內存始終保持在 256MB(物理內存大小) * 10% = 2.56MB 左右,當髒頁達到10%的時候就開始大量使用swap。

這個10%來自" /proc/sys/vm/dirty_background_ratio "。

可調優性能參數:

1、通過調節緩存的髒數據同步到硬盤的策略髒數據表示沒有被當前的線程使用的數據

例如: echo 10 > /proc/sys/vm/dirty_background_ratio(當髒數據佔據物理內存10%時,觸發pdflush同步到硬盤):小心調節,會大幅度的影響性能;

echo 2000 > /proc/sys/vm/dirty_expire_centisecs(當髒數據在物理內存的逗留時間超過2000ms時被同步到硬盤);

2、通過調節swap參數,來優化linux虛擬內存管理基於程序的局部性原理,linux通過虛擬內存機制來實現併發運行進程,linux發現物理內存不夠用時,會根據LRU算法將一部分內存swap out到硬盤;當運行被換出的那個線程時,在swap in 到內存裏;

例如: echo 10 > /proc/sys/vm/swappiness (值爲0表示儘量都用物理內存,值爲100表示積極的使用swap分區;)這個參數很重要;小心調節; 一般爲60;在緊急處理線上問題時,可以緊急使用一下。

一、操作系統設置swap的目的

程序運行的一個必要條件就是足夠的內存,而內存往往是系統裏面比較緊張的一種資源。爲了滿足更多程序的要求,操作系統虛擬了一部分內存地址,並將之映射到swap上。對於程序來說,它只知道操作系統給自己分配了內存地址,但並不清楚這些內存地址到底映射到物理內存還是swap。物理內存和swap在功能上是一樣的,只是因爲物理存儲元件的不同(內存和磁盤),性能上有很大的差別。操作系統會根據程序使用內存的特點進行換入和換出,儘可能地把物理內存留給最需要它的程序。但是這種調度是按照預先設定的某種規則的,並不能完全符合程序的需要。一些特殊的程序(比如MySQL)希望自己的數據永遠寄存在物理內存裏,以便提供更高的性能。於是操作系統就設置了幾個api,以便爲調用者提供“特殊服務”。

二、Linux提供的幾個api

1、mlockall()和munlockall()

這一對函數,可以讓調用者的地址空間常駐物理內存,也可以在需要的時候將此特權取消。mlockall()的flag位可以是MCL_CURRENT和MCL_FUTURE的任意組合,分別代表了“保持已分配的地址空間常駐物理內存”和“保持未來分配的地址空間常駐物理內存”。對於Linux來說,這對函數是非常霸道的,只有root用戶纔有權限調用

2、shmget()和shmat()

這一對函數,可以向操作系統申請使用大頁內存(Large Page)。大頁內存的特點是預分配和永駐物理內存,因爲使用了共享內存段的方式,page table有可能會比傳統的小頁分配方式更小。對於多進程共享內存的程序(比如ORACLE),大頁內存能夠節省很多page table開銷;

而對於MySQL來說,性能和資源開銷沒有顯著變化,好處就在於減少了內存地址被映射到swap上的可能。至於爲什麼是減少,而不是完全避免,之後再講解。

3、O_DIRECT和posix_memalign()

以上兩個方法都不會減少內存的使用量,調用者的本意是獲取更高的系統特權,而不是節約系統資源。O_DIRECT是一種更加理想化的方式,通過避免double buffer,節省了文件系統cache的開銷,最終減少swap的使用率。O_DIRECT是Linux  IO調度相關的標誌,在open函數裏面調用。通過O_DIRECT標誌打開的文件,讀寫都不會用到文件系統的cache。傳統的數據庫(ORACLE、MySQL)基本都有O_DIRECT相關的開關,在提高性能的同時,也減少了內存的使用。至於posix_memalign(),是用來申請對齊的內存地址的。只有用posix_memalign()申請的內存地址,才能用來讀寫O_DIRECT模式下的文件描述符。

4、madvise()和fadvise()

這對函數也是比較溫和的,可以將調用者對數據訪問模式的預期傳遞給Linux,以期得到更好的性能。我們比較感興趣的是MADV_DONTNEED和FADV_NOREUSE這兩個flag。前者會建議Linux釋放指定的內存區域,而後者會建議文件系統釋放指定文件所佔用的cache。

 

當mysql出現內存導致的性能瓶頸時,可以:

1、/proc/sys/vm/swappiness的內容改成0(臨時),/etc/sysctl.conf上添加vm.swappiness=0(永久)

這個參數決定了Linux是傾向於使用swap,還是傾向於釋放文件系統cache。在內存緊張的情況下,數值越低越傾向於釋放文件系統cache。當然,這個參數只能減少使用swap的概率,並不能避免Linux使用swap。

2、修改MySQL的配置參數innodb_flush_method,開啓O_DIRECT模式。

這種情況下,InnoDB的buffer pool會直接繞過文件系統cache來訪問磁盤,但是redo log依舊會使用文件系統cache。值得注意的是,Redo log是覆寫模式的,即使使用了文件系統的cache,也不會佔用太多。

3、添加MySQL的配置參數memlock

這個參數會強迫mysqld進程的地址空間一直被鎖定在物理內存上,對於os來說是非常霸道的一個要求。必須要用root帳號來啓動MySQL才能生效。

4、還有一個比較複雜的方法,指定MySQL使用大頁內存(Large Page)。Linux上的大頁內存是不會被換出物理內存的,和memlock有異曲同工之妙。具體的配置方法可以參考:http://harrison-fisk.blogspot.com/2009/01/enabling-innodb-large-pages-on-linux.html

 

第三節: 磁盤I/O可調性能參數 

linux的子系統VFS(virtural file system)虛擬文件系統;從高層將各種文件系統,以及底層磁盤特性隱藏,對程序員提供:read,write,delete等文件操作;這就是之所以我們可以在linux上mount多種不同格式的文件系統的,而window確不行;

當然基於:虛擬文件系統,文件系統,文件系統驅動程序,硬件特性方面,都能找到性能瓶頸;

1、選擇適合應用的文件系統;

2、調整進程I/O請求的優先級,分三種級別:1代表 real time ; 2代表best-effort; 3代表idle ;

如:ionice -c1 -p 1113(給進程1113的I/O優先級設置爲最高優先級)

3、根據應用類型,適當調整page size 和block size;

4、升級驅動程序; 

 

第四節 :網絡可調性能參數

對於我們web應用來說,網絡性能調整如此重要,linux的網絡支持是無與倫比的;是作爲網絡服務器的首先;對於web服務來說:除了應用的響應速度外,linux網絡管理子系統,網卡,帶寬都可能成爲性能瓶頸;

網絡參數可以在/proc/sys/net/ipv4/   下面的文件中進行配置。

可以查看和設置的參數:

1、查看網卡設置是否全雙工傳輸的: echtool eth0

2、設置MTU(最大傳輸單元),在帶寬G以上的時候,要考慮將MTU增大,提高傳輸性能;

如: ifconfig eth0 mtu 9000 up #如果數據包的長度大於mtu的長度時,很容易出現丟包情況。

3、增加網絡數據緩存;傳輸數據時linux是將包先放入緩存,填滿緩存後即發送出去;讀操作類似;

sysctl -w net.ipv4.tcp_rmem="4096 87380 8388608" :設置tcp讀緩存:最小緩存,初始化時,最大緩存

sysctl -w net.ipv4.tcp_wmem="4096 87380 8388608" :設置tcp寫緩存:最小緩存,初始化時,最大緩存

由於是先將數據放入緩存再發送,或收取收據,那麼當內存緊張或內存不夠用時,網絡丟包就可能出現。

4、禁用window_scaling(窗口大小的位數定義),並且直接設置window_size

sysctl -w net.ipv4.tcp_window_scaling=0

5、設置TCP連接可重用性: 對於TIME_OUT狀態的TCP連接可用於下一個TCP重用,這樣減少了三次握手和創建時間,非常提高性能,尤其對於web server;

如: 開啓可重用tcp功能: sysctl -w net.ipv4.tcp_tw_reuse=1 sysctl -w net.ipv4.tcp_tw_recyle=1

6、禁用掉沒必要的tcp/ip協議功能:比如icmp;broadcast包的接收;

7、linux對於keeplive的tcp連接有一個默認的過期時間;可以減小這個時間,讓沒用的連接釋放掉,畢竟tcp連接數是有限的嘛;

     如: sysctl -w net.ipv4.tcp_keepalive_time=1800 (設置過期時間,1800s)

8、設置最大tcp正在連接狀態(還沒ESTABLISHED)隊列長度;避免由於太多的tcp連接過來,導致服務器掛掉;比如DoS***

如:sysctl -w net.ipv4.tcp_max_syn_backlog=4096

9、 綁定tcp類型的中斷到一個cpu上;(讓cpu去親和這個類型中斷,避免頻繁的中斷,影響線程調度性能)

 

總結: 我們在性能優化一個應用時,首要的是設定優化要達到的目標,然後尋找瓶頸,調整參數,達到優化目的;但是尋找瓶頸時可能是最累的,要從大範圍,通過很多用例,很多測試報告,不斷的縮小範圍,最終確定瓶頸點;以上這些參數只是個認識,系統性能優化中可能用到,但並不是放之四海而皆準的; 有的參數要邊測試,邊調整的;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章