從壓測到調優:Nginx高併發效能最佳化全鏈路指南,輕鬆突破TPS瓶頸!

前言

在做併發最佳化前,瞭解下什麼叫做併發

連線與請求

  • 連線:指的是客戶端和伺服器之間的TCP連線。在HTTP/1.1及更高版本中,預設啟用了Keep-Alive連線,允許多個HTTP請求複用一個TCP連線。
  • 請求:指的是在一個TCP連線中,客戶端向伺服器傳送的具體HTTP請求。

併發連線數

併發連線數通常指的是在某一時間點上,伺服器同時處理的活躍TCP連線數。這與每個連線中傳送的請求數無關。因此:
  • 如果一個客戶端建立一個TCP連線(並保持該連線開啟),則這個連線會被算作一個併發連線。
  • 在一個併發連線內,即使客戶端每秒傳送多個請求,該連線在計數上仍然算作一個併發連線。

請求處理能力

伺服器處理請求的能力可以用請求率來衡量,通常以每秒處理的請求數(RPS,即Requests Per Second)為單位。在一個TCP連線中:
  • 單個併發連線:如果客戶端在一個連線中每秒傳送多個請求,伺服器需要處理的請求數增加,但併發連線數保持不變。
  • 多個併發連線:如果有多個併發連線,每個連線中都在傳送多個請求,伺服器需要處理的總請求數和總連線數都會增加。

配置和監控

  1. Nginx配置
    • 連線數:由worker_processesworker_connections決定。
    • 請求數:Nginx高效處理請求的能力與事件驅動架構有關。
  2. HAProxy配置
    • 連線數:由maxconn引數決定。
    • 請求數:可以透過調整佇列和緩衝區來最佳化處理能力。

示例場景

假設有一個Nginx伺服器,配置如下:
worker_processes4;events {worker_connections1024;}
根據配置,每個工作程序可以處理1024個連線,因此總共可以處理的最大併發連線數是:
4×1024=4096
假設每個連線中的客戶端每秒傳送10個請求,那麼在處理最大併發連線數的情況下,每秒的總請求數是:
4096×10=40960 RPS

瞭解完什麼是併發後,看下如何檢視併發和請求

即時監控

透過即時監控連線數和請求數,可以更好地瞭解伺服器的負載情況。

Nginx

使用stub_status模組檢視當前連線數和請求數:
location/nginx_status {stub_status;allow127.0.0.1;denyall;}
檢視指標
Activeconnections: 291serveraccepts handled requests802024802024 1604037Reading: 12 Writing: 43 Waiting: 236

引數詳細解釋

  1. Active connections: 291
    • 解釋:當前正在處理的活躍連線數。這包括正在讀取請求、傳送響應和處於Keep-Alive狀態的連線。
    • 作用:反映當前Nginx伺服器的總負載情況。
  2. server accepts handled requests
    • 802024(accepts):伺服器接受的總連線數。
    • 802024(handled):成功處理的總連線數。通常與accepts相同,除非Nginx由於資源限制或其他原因放棄了一些連線。
    • 1604037(requests):處理的總請求數。因為一個連線可以處理多個請求(Keep-Alive連線),所以這個值通常大於handled的值。
    • 解釋:這行包含三個累積計數器,分別表示自Nginx啟動以來的總連線數、總處理的連線數和總處理的請求數。
    • 各個值的含義
  3. Reading: 12
    • 解釋:當前Nginx正在讀取客戶端請求頭的連線數。
    • 作用:反映正在處理請求頭資料的連線數量,有助於瞭解當前的輸入流量。
  4. Writing: 43
    • 解釋:當前Nginx正在向客戶端傳送響應資料的連線數。
    • 作用:反映正在處理響應輸出的連線數量,有助於瞭解輸出流量和處理速度。
  5. Waiting: 236
    • 解釋:處於Keep-Alive狀態、等待下一次請求的空閒連線數。
    • 作用:反映連線保持活動但當前沒有傳輸資料的連線數量。這些連線可能會隨時傳送新的請求。

如何使用這些資訊

  • Active connections如果這個值過高,可能意味著伺服器負載過大,需要增加Nginx例項或調整配置。
  • accepts和handled:通常這兩個值相等,如果有顯著差異,可能存在連線被拒絕或處理失敗的情況。
  • requests這個值隨著時間增長,反映了伺服器處理的請求量。高請求數可能需要最佳化Nginx配置或後端應用。
  • Reading和Writing:這些值幫助識別當前伺服器主要是接收資料(Reading)還是傳送資料(Writing),有助於分析效能瓶頸。
  • Waiting:高等待數表示大量Keep-Alive連線,如果伺服器資源有限,可以考慮調整Keep-Alive超時時間以減少等待連線數。

 併發計算方式

nginx 併發量計算:最大併發連線數=worker_processes×worker_connections
haproxy併發量計算:

系統資源限制

在設定HAProxy的最大連線數之前,必須確保作業系統支援所需的檔案描述符數量。每個連線通常需要一個檔案描述符,因此要確保系統的檔案描述符限制足夠高。
臨時設定限制(僅對當前會話有效):
ulimit -n 65535
永久設定限制(編輯 /etc/security/limits.conf):
* soft nofile

65535

* hard nofile

65535

還需要調整系統的核心引數,以支援大量的併發連線。編輯 /etc/sysctl.conf 檔案,並新增以下設定:
net.core.somaxconn=10240net.ipv4.tcp_max_tw_buckets=5000net.ipv4.tcp_max_syn_backlog=5000net.ipv4.tcp_fin_timeout=30net.ipv4.ip_local_port_range = 1024 65535
全域性所有程序可開啟的檔案描述符數量
[root@master-1 ~]# cat /proc/sys/fs/file-max6815744
配置HAProxy的最大連線數
假設系統已經配置好檔案描述符限制和核心引數,可以根據實際需求設定HAProxy的global maxconn引數。由於你提到的Nginx示例是4核,每個核可以處理65535個連線,總計約26萬連線,我們可以使用類似的配置來設定HAProxy。
globalmaxconn100000 # 不能超過系統檔案描述符chroot/usr/local/haproxystatssocket /var/lib/haproxy/haproxy.sock mode 600 level adminuid188gid188daemon#nbproc 2nbthread4cpu-map1/1 0cpu-map1/2 1cpu-map1/3 2cpu-map1/4 3pidfile/var/lib/haproxy/haproxy.pidlog127.0.0.1 local3 infospread-checks5defaultsoptionhttp-keep-aliveoptionforwardforoptionredispatchmaxconn100000 modehttptimeouthttp-keep-alive 120stimeoutconnect 1000mstimeoutclient 600mstimeoutserver 600mstimeoutcheck 5slistenstatsmodehttpbind0.0.0.0:9999statsenablestatsuri /haproxy-statusstatsauth haadmin:123456listenkube-apiserverbalanceroundrobinbind0.0.0.0:8443serverweb1 192.168.0.120:6443 check inter 3000 fall 2 rise 3serverweb2 192.168.0.61:6443 check inter 3000 fall 2 rise 3serverweb3 192.168.0.192:6443 check inter 3000 fall 2 rise 3listennginxbalanceroundrobinbind0.0.0.0:8079serverweb1 192.168.0.120:8078 check inter 3000 fall 2 rise 3serverweb2 192.168.0.61:8078 check inter 3000 fall 2 rise 3

注意事項

  1. 系統資源監控:儘管理論上可以設定很高的最大連線數,但實際使用中應該監控系統資源(CPU、記憶體、網路等)的使用情況,確保不會因為過高的併發連線數導致系統資源耗盡。
  2. 連線數配置一致性:確保作業系統、Nginx和HAProxy的檔案描述符限制配置一致,避免不一致導致連線失敗。
  3. 效能測試:在生產環境中使用前,進行充分的效能測試,以確定系統能夠穩定處理配置的最大連線數。

引數調優

[root@master-1 ~]# ulimit -n

65535

[root@master-1 ~]# cat /proc/sys/fs/file-max

6815744

這兩有什麼區別嗎,為什麼不一樣

作用範圍:

ulimit -n:針對單個使用者程序,設定單個程序可以開啟的檔案描述符數。

/proc/sys/fs/file-max:針對整個系統,設定系統所有程序可以開啟的檔案描述符總數。

實際應用

假設一個系統有多個使用者程序,每個程序的檔案描述符限制是65535,如果有100個這樣的程序同時執行,理論上它們最多可以使用65535 * 100 = 6553500個檔案描述符。但是,由於系統的總限制是6815744,這意味著即使每個程序設定了較高的檔案描述符限制,總數也不能超過系統級的6815744。

nginx高可用叢集安裝,並使用haproxy+keepalived做代理

兩臺nginx+haproxy+keepalived

192.168.0.120
192.168.0.61

nginx 部分配置

usernginx;worker_processesauto;worker_cpu_affinityauto;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;worker_rlimit_nofile65535; # 每個工作程序可以開啟的檔案描述符數量events{worker_connections65535; # 每個工作程序可以連線的數量useepoll;accept_mutexon;multi_accepton;}http{includemime.types;default_typeapplication/octet-stream;sendfileon; #tcp_nopush on; #keepalive_timeout 0;keepalive_timeout65;gzipon;server{listen8078;server_namelocalhost; #charset koi8-r; #access_log logs/host.access.log main;location/ {roothtml;indexindex.html index.htm;}location/nginx_status {stub_status;access_logoff;}}

haproxy配置

globalmaxconn100000chroot/usr/local/haproxystatssocket /var/lib/haproxy/haproxy.sock mode 600 level adminuid188gid188daemon#nbproc 2nbthread4cpu-map1/1 0cpu-map1/2 1cpu-map1/3 2cpu-map1/4 3pidfile/var/lib/haproxy/haproxy.pidlog127.0.0.1 local3 infospread-checks5defaultsoptionhttp-keep-aliveoptionforwardforoptionredispatchmaxconn100000modehttptimeouthttp-keep-alive 120stimeoutconnect 1000mstimeoutclient 600mstimeoutserver 600mstimeoutcheck 5slistenstatsmodehttpbind0.0.0.0:9999statsenablestatsuri /haproxy-statusstatsauth haadmin:123456listennginxbalanceroundrobinbind0.0.0.0:8079serverweb1 192.168.0.120:8078 check inter 3000 fall 2 rise 3serverweb2 192.168.0.61:8078 check inter 3000 fall 2 rise 3

keepalived

! Configuration File for keepalivedglobal_defs{notification_email{[email protected][email protected][email protected]}router_idhaproxy-2}vrrp_scriptchk_haproxy {userrootscript"/etc/keepalived/check_haproxy.sh"interval2weight-10}vrrp_instanceVI_1 {stateBACKUPinterfaceeth0virtual_router_id51priority110nopreemptadvert_int1authentication{auth_typePASSauth_pass88888888}virtual_ipaddress{192.168.0.190}track_script{chk_haproxy}}

 ab壓力測試工具講解

使用ab命令,對nginx進行壓力測試1、安裝ab命令yum install httpd-tools -yapt install apache2-utils2、使用ab命令對nginx傳送大量的連結-n 請求數量 # 一共發出多少個請求 -n 10000-c 請求併發數 -c 100-k # 表示啟動keepalived保持連結功能ab -kc 1000 -n 100000http://127.0.0.1/

安裝磁碟檢視工具

yum install sysstat
引數詳解ab-c 1000 -n 10000 http://192.168.2.38/# -c指定1000併發,-n指定總10000次,相當於1000個人訪問10次。# -k 是否開啟長連線ServerSoftware: nginx/1.8.1 #伺服器資訊和版本ServerHostname: 192.168.2.38 #伺服器的域名ServerPort: 80 #埠DocumentPath: / #訪問的路徑DocumentLength: 612 bytes #文件的大小為 612 bytes(此為http響應的正文長度)ConcurrencyLevel: 1000 #併發請求數Timetaken for tests: 0.287 seconds #整個測試持續的時間,預設秒Completerequests: 1000 #完成的請求數Failedrequests: 0 #失敗的請求書Writeerrors: 0 #網路連線寫入錯誤數Totaltransferred: 844000 bytes #傳輸的總資料量HTMLtransferred: 612000 bytes #傳輸的HTML內容傳輸量Requestsper second: 3485.11 [#/sec] (mean) #平均每秒請求數Timeper request: 286.935 [ms] (mean) #所有使用者都請求一次的平均時間Timeper request: 0.287 [ms] (mean, across all concurrent requests) #單個使用者請求一次的時間Transferrate: 2872.49 [Kbytes/sec] received #傳輸速率ConnectionTimes (ms)minmean[+/-sd] median maxConnect: 0 84 4.1 84 94Processing: 86 99 6.6 100 109Waiting: 0 83 16.2 84 108Total: 95 183 7.4 182 195#所有服務請求的百分比佔用時間,這裡50%的請求用時182ms,一般看90%的部分Percentageof the requests served within a certain time (ms)50%18266%18875%19180%19290%19395%19498%19499%194100%195 (longest request)

併發測試

 代理後併發與單個nginx併發對比
可以看到每秒請求數,單個請求用時,請求速率,百分比用時都大大縮小。

如何設定監控呢

使用Prometheus監控Nginx的請求數是一個有效的方法。為了計算1分鐘內處理的請求數,我們需要定義適當的範圍,並瞭解如何監控和評估這些資料。

設定合理的範圍

  1. 基準測試和容量規劃
    • 在定義合適的請求範圍前,首先需要了解Nginx伺服器的處理能力。這可以透過基準測試來獲得。
    • 使用工具如ab(ApacheBench)、wrkJMeter進行負載測試,確定Nginx在不同負載條件下的效能表現。

示例

假設在基準測試中,Nginx伺服器的處理能力是每秒1000個請求(RPS),那麼1分鐘內處理的請求數理論最大值為:
1000 RPS×60 seconds=60000 requests/minute
在實際生產環境中,可能會有不同的負載情況:
  • 低負載:1000 – 5000 requests/minute
  • 中等負載:5000 – 20000 requests/minute
  • 高負載:20000 – 60000 requests/minute
使用Prometheus監控資料可以幫助確定實際的負載範圍。例如,查詢結果顯示過去1分鐘的請求數在20000 – 60000之間,結合伺服器的資源使用情況和響應時間,可以評估這個範圍是否合理。
連結:https://www.cnblogs.com/rtnb/p/18238885
(版權歸原作者所有,侵刪)

相關文章