今天同事告訴我安裝的 Haproxy 代理 Ceph 經過壓力測試軟件壓測的時候,使用與直接壓主機的配置去壓 Haproxy 的時候會被壓死。mysql
咱們使用 Ceph 作對象存儲,使用 Haproxy 代理 Ceph 兩個網關,作負載均衡及高可用。
Haproxy 的工做狀況大體是將從網卡接收到的數據寫到內存緩存下,再從網卡寫出。
在操做系統看流程是這樣的:網卡接收到請求,經過中斷告知 CPU,CPU 根據操做系統的計算,分配一塊內存給網卡寫入數據,內核將數據從內核空間複製到用戶空間,haproxy 接收到數據,根據負載策略選擇一個 IP 地址,將數據寫出,從用戶空間複製到內核空間,而後內核調用網卡寫出。
這有點像是用瓢在兩個缸倒水,想要儘快倒完,能夠增快倒水速度(CPU頻率),增長人數(進程數),把瓢作大點(緩存)。
分析完這個流程,首先想到的是先去調多工做進程數,與 CPU 數量一致或少一個便可,再完成進程綁定操做。
其次看可否調整 haproxy 的 IO 模型。
代理對象存儲,傳輸數據量較大,能夠調整 tcp 鏈接相關參數來調整數據緩存。
Haproxy 是工做在用戶空間的應用,與 lvs 工做方式不一樣,僅是模擬 tcp 代理,查看文件打開數量限制。
大膽猜想下 Haproxy 由於緩存過小頻繁操做,致使 CPU 飆升。資源佔用太多被內核殺掉,後資源空閒 systemd 檢測到程序異常,主動啓動應用。開啓進程數需先關注。面試
# 查看物理CPU個數 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l 32 # 查看每一個物理CPU中core的個數(即核數) cat /proc/cpuinfo| grep "cpu cores"| uniq 1 # 查看邏輯CPU的個數 cat /proc/cpuinfo| grep "processor"| wc -l 32
free -g total used free shared buff/cache available Mem: 62 0 61 0 1 61 Swap: 15 0 15
32C 62G
ps -ef | grep haproxy ipaas 11140 10112 0 17:29 pts/1 00:00:00 grep --color=auto haproxy root 14232 1 0 Jun12 ? 00:00:00 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid haproxy 14233 14232 0 Jun12 ? 00:00:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds haproxy 14234 14233 0 Jun12 ? 01:11:26 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds # 注意: haproxy-systemd-wrapper 從名字上看只是一個配合 systemd 作兼容的。兩個 /usr/sbin/haproxy 進程其中一個是 status 收集狀態的,另一個是工做進程。在設定進程數時要注意。進程數 = CPU數 - 內核佔用0號CPU - status 佔用一個CPU。 ps -ef | grep haproxy | wc -l # 彷佛不用執行這個了 明顯兩個工做進程 # 查看進程在那顆CPU上運行 ps axo psr,command | grep haproxy
至此已經能夠去設置進程數以及進程親緣性綁定來實現必定程度上的優化,爲了驗證下前面的猜想先不作優化,看看是否猜對了。sql
# CPU 相關 # 查看每CPU負載 #輸入top 按 1 # 查看 CPU 負載類型 mpstat -P ALL 1 # 查看 HAProxy 進程調用哪一個系統調用,佔用cpu 最多 # strace -p pid -c # 網絡相關 # 查看 socket的listen 隊列 watch "cat /proc/net/netstat | awk '/TcpExt/ { print \$21,\$22 }'" # 查看某進程由哪一個cpu執行 ps axo psr,command | grep haproxy
壓測數據
緩存
由第一個可知 僅有一個 haproxy 進程佔用 CPU 較高,右側圖看到消耗內存較少,左下圖可知沒有包丟失,右下角可知沒什麼高負載,或者說總體悠閒,這點在左上角圖 96.9 id也能夠得知。服務器
進程信息
cookie
有個 haproxy 進程在不斷切換 CPU網絡
此次沒壓死,可是這個結果甚是意外,性能至關不錯app
各個進程CPU使用率在 8% 上下。負載均衡
看到這個結果我內心哇涼哇涼的,這意味着僅調整進程數,瓶頸就不會出如今 haproxy。估計5個進程就會讓後面的 Ceph 出現瓶頸,固然可能本機內核參數也會出現影響。先暫時作以下調整:1 調整工做進程爲 30,並完成進程綁定,注意留出給內核與stats。2 調整最大鏈接數爲 65535。內核參數暫不作修改。下面給出影響較大的內核參數。frontend
# 注 下面完成了工做進程數及親緣性綁定,若想作的極致一點還能夠經過在內核啓動文件即 grub 文件啓動參數來實現 內核進程綁定以及進程隔離 # 至於中斷隔離不建議使用 # 與此相關的配置有 global nbproc 4 # 配置進程數,不包含 status cpu-map 1 1 # 親緣性綁定。前一個數字是進程號,後一個數字是CPU內核的號,注意將0號cpu留給內核 cpu-map 2 2 cpu-map 3 3 cpu-map 4 4 ... cpu-map 30 30 stats bind-process 31 # 能夠將不一樣任務綁定到不一樣的內核上獨立執行 frontend access_http bind 0.0.0.0:80 # bind-process 1 # 將進程與任務綁定,暫不處理 frontend access_https bind 0.0.0.0:443 ssl crt /etc/yourdomain.pem # bind-process 2 3 4
global maxconn 65535
# 默認的TCP數據接收窗口大小(字節)默認 256K net.core.rmem_default = 524288 # 最大的TCP數據接收窗口(字節) 默認4M,根據文件大小調整下面的是 48M 較大 net.core.rmem_max = 50331648 # 默認的TCP數據發送窗口大小(字節) net.core.wmem_default = 524288 # 最大的TCP數據發送窗口(字節)默認4M,根據文件大小調整下面的是 32M 較大 net.core.wmem_max = 33554432 # 定義了系統中每個端口最大的監聽隊列的長度,這是個全局的參數 net.core.somaxconn = 65535 # TCP/UDP協議容許使用的本地端口號範圍 net.ipv4.ip_local_port_range = 1025 65534 # 容許綁定不存在的 IP net.ipv4.ip_nonlocal_bind = 1 # 表示是否打開TCP同步標籤(syncookie),同步標籤能夠防止一個套接字在有過多試圖鏈接到達時引發過載 # 內核必須打開了CONFIG_SYN_COOKIES項進行編譯, net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_syn_retries = 2 # 表示開啓TCP鏈接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉 net.ipv4.tcp_tw_recycle = 1 # 容許將TIME-WAIT sockets從新用於新的TCP鏈接,默認爲0,表示關閉 net.ipv4.tcp_tw_reuse = 1 # 最大限度使用物理內存,即物理內存使用完後再使用 swap vm.swappiness = 0