從RocketMQ源碼腳本看OS參數優化

1 提要

RocketMQ是一款優秀的消息中間件,從它的啓動腳本配置中可以學習到os參數優化的一些思路和經驗。但是也不能直接照搬,需要理解其中的參數詳解,對比當前項目場景是否適用。用的時候也需要進行多方測試,以免出現問題,千萬不要瞎優化。

RocketMQ爲了實現高性能高吞吐,對一些參數的調整比較激進。RocketMQ的部署建議是最好在物理實體機上,該機器上不要部署其他同樣需要大量資源的軟件。

2 從os.sh腳本看參數優化

os.sh腳本位置在 https://github.com/apache/rocketmq/blob/master/distribution/bin/os.sh
該腳本建議一些優化的參數如下:

sudo sysctl -w vm.overcommit_memory=1
sudo sysctl -w vm.drop_caches=1
sudo sysctl -w vm.zone_reclaim_mode=0
sudo sysctl -w vm.max_map_count=655360
sudo sysctl -w vm.dirty_background_ratio=50
sudo sysctl -w vm.dirty_ratio=50
sudo sysctl -w vm.dirty_writeback_centisecs=360000
sudo sysctl -w vm.page-cluster=3
sudo sysctl -w vm.swappiness=1

echo 'ulimit -n 655350' >> /etc/profile
echo '* hard nofile 655350' >> /etc/security/limits.conf

echo '* hard memlock      unlimited' >> /etc/security/limits.conf
echo '* soft memlock      unlimited' >> /etc/security/limits.conf

DISK=`df -k | sort -n -r -k 2 | awk -F/ 'NR==1 {gsub(/[0-9].*/,"",$3); print $3}'`
[ "$DISK" = 'cciss' ] && DISK='cciss!c0d0'
echo 'deadline' > /sys/block/${DISK}/queue/scheduler

linux vm參數的含義可以在 https://sysctl-explorer.net/vm/ 上找到相應解釋。有些參數不好用中文描述,需要沿用英文解釋。有些參數使用案例資料太少,只能找一些解釋參考下

2.1 vm.overcommit_memory=1

可選值:0、1、2。
0, 表示內核將檢查是否有足夠的可用內存供應用進程使用;如果有足夠的可用內存,內存申請允許;否則,內存申請失敗,並把錯誤返回給應用進程。
1, 表示內核允許分配所有的物理內存,而不管當前的內存狀態如何。
2, 表示內核允許分配超過所有物理內存和交換空間總和的內存
將這個參數的值調整爲1,意思是把所有可用的物理內存都允許分配給你,只要有內存就給你來用,這樣可以避免申請內存失敗的問題

2.2 vm.drop_caches=1

0:開啓緩存機制
1:清空頁緩存
2:清空inode和目錄樹緩存
3:清空所有緩存

大多數GNU Linux都是默認開啓了緩存機制的,查看配置文件 cat /proc/sys/vm/drop_caches 若爲0的話,則表示開啓了緩存機制的,這種機制在一直運行某個服務的時候非常有效,便於服務本身的快速讀取,而作爲桌面用戶來說,打開的程序並不那麼單一,所以桌面用戶還是建議設置此配置文件爲1,及時對系統緩存進行清理,釋放空間以供其它程序使用

2.3 vm.zone_reclaim_mode=0

Zone_reclaim_mode allows someone to set more or less aggressive approaches to reclaim memory when a zone runs out of memory. If it is set to zero then no zone reclaim occurs Allocations will be satisfied from other zones / nodes in the system.

This is value ORed together of
1 = Zone reclaim on
2 = Zone reclaim writes dirty pages out
4 = Zone reclaim swaps pages

如果將其設置爲零,則不會發生區域回收。
該參數和cpu的NUMA架構有關。
簡單點說,NUMA(Non-Uniform Memory Access)是對UMA(Uniform Memory Access)架構的優化。
UMA: 每個CPU核共享相同的內存地址空間。但隨着CPU核心數的增加,架構會遇到問題,比如對總線的帶寬帶來挑戰、訪問同一塊內存的衝突問題。
NUMA: 不同的內存和CPU核從屬不同的 Node,每個 Node 都有自己的集成內存控制器(IMC,Integrated Memory Controller)。在 Node 內部,架構類似SMP,使用 IMC Bus 進行不同核心間的通信;不同的 Node 間通過QPI(Quick Path Interconnect)進行通信.有點多級Bus的意味。

NUMA參考:https://www.jianshu.com/p/0607c5f62c51
zone_reclaim_mode詳細解釋參考: https://sysctl-explorer.net/vm/zone_reclaim_mode/

2.4 vm.max_map_count=655360

通俗點講,該參數表示可以開啓的線程的數量。如果這個參數過小,可能會導致中間件無法開啓足夠的線程,進而導致報錯。默認值是65536,但是這個值是不夠的,需要把這個參數調大

2.5 vm.dirty_background_ratio=50

2.6 vm.dirty_ratio=50

2.7 vm.dirty_writeback_centisecs=360000

以上3個參數都是與髒頁緩存相關的。參考此文章描述:https://feichashao.com/dirty_ratio_and_dirty_background_ratio/

vm.dirty_background_ratio: 是內存可以填充“髒數據”的百分比。這些“髒數據”在稍後是會寫入磁盤的,pdflush/flush/kdmflush這些後臺進程會稍後清理髒數據。舉一個例子,我有32G內存,那麼有3.2G的內存可以待着內存裏,超過3.2G的話就會有後來進程來清理它。

vm.dirty_ratio: 是絕對的髒數據限制,內存裏的髒數據百分比不能超過這個值。如果髒數據超過這個數量,新的IO請求將會被阻擋,直到髒數據被寫進磁盤。這是造成IO卡頓的重要原因,但這也是保證內存中不會存在過量髒數據的保護機制。

vm.dirty_writeback_centisecs: 指定多長時間 pdflush/flush/kdmflush 這些進程會起來一次

2.8 vm.page-cluster=3

page-cluster是用來控制從swap空間換入數據的時候,一次連續讀取的頁數,這相當於對交換空間的預讀。這裏的連續是指在swap空間上的連續,而不是在內存地址上的連續。因爲swap空間一般是在硬盤上,對硬盤設備的連續讀取將減少磁頭的尋址,提高讀取效率。這個文件中設置的值是2的指數。就是說,如果設置爲0,預讀的swap頁數是2的0次方,等於1頁。如果設置爲3,就是2的3次方,等於8頁。同時,設置爲0也意味着關閉預讀功能

2.9 vm.swappiness=1

swappiness的值的大小對如何使用swap分區是有着很大的聯繫的。swappiness=0的時候表示最大限度使用物理內存,然後纔是 swap空間,swappiness=100的時候表示積極的使用swap分區,並且把內存上的數據及時的搬運到swap空間裏面。
從性能上來說,當然越小性能越好,但是也不能小到等於0,0表示別把任何一個進程放到磁盤swap區域去,可能會造成系統崩潰。

2.10 調大限制最大打開文件描述符參數

echo ‘ulimit -n 655350’ >> /etc/profile
echo ‘* hard nofile 655350’ >> /etc/security/limits.conf

echo ‘* hard memlock unlimited’ >> /etc/security/limits.conf
echo ‘* soft memlock unlimited’ >> /etc/security/limits.conf

如果不調大這些參數,會遇到too many open files之類的錯誤,相信部署過elasticsearch等中間件的小夥伴對這種報錯信息不會陌生。
ps:
ulimit -n 655350 調大每個進程默認打開的最大文件句柄數
memlock 最大鎖定內存地址空間

2.11 磁盤I/O隊列調度策略

DISK=`df -k | sort -n -r -k 2 | awk -F/ 'NR==1 {gsub(/[0-9].*/,"",$3); print $3}'`
[ "$DISK" = 'cciss' ] && DISK='cciss!c0d0'
echo 'deadline' > /sys/block/${DISK}/queue/scheduler

腳本含義: 遍歷所有磁盤,找到符合條件的磁盤,對其使用deadline調度策略

對於磁盤I/O,Linux提供了cfq, deadline和noop三種調度策略
cfq: 這個名字是Complete Fairness Queueing的縮寫,它是一個複雜的調度策略,按進程創建多個隊列,試圖保持對多個進程的公平(這就沒考慮讀操作和寫操作的不同耗時)
deadline: 這個策略比較簡單,只分了讀和寫兩個隊列(這顯然會加速讀取量比較大的系統),叫這個名字是內核爲每個I/O操作都給出了一個超時時間
noop: 這個策略最簡單,只有單個隊列,只有一些簡單合併操作
考慮到硬件配置、實際應用場景(讀寫比例、順序還是隨機讀寫)的差異,上面的簡單解釋對於實際選擇沒有太大幫助,實際該選擇哪個基本還是要實測來驗證。不過下面幾條說明供參考:
根據多篇文章的說法,deadline和noop差異不是太大,但它們倆與cfq差異就比較大。
參考資料: https://www.cnblogs.com/bamanzi/p/linux-disk-io-scheduler.html

3 總結

由於並不是專業的linux運維,有些參數網上資料較少,講的也比較模糊,先做個記錄,有時間再找資料研究下參數的含義和使用場景。不過我們從中可以學習到os內核參數優化的大體思路。學習總結,有時候需要抓大放小

歡迎關注我的微信公衆號: wanjinyu的技術小窩

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