Nginx 高階篇(九)單機併發 1 萬 10 萬次請求解決和優化方案

huxiaobai_001發表於2020-03-21

前提!必須宣告前提!
前提:我這裡只是調通nginx支撐單機1萬併發100000次請求甚至更高 不帶後邊的php-fpm mysql memcache的tcp連結玩哈!光調整nginx併發1萬10萬次請求就夠費勁的 後邊帶上php-fpm或者mysql memcache還得要進行優化 哪那麼簡單 草!
Nginx 高階篇(八)ab 壓力測試即 nginx 的效能統計模組
這篇文章的最後我們提到ab測試 併發10000 訪問量20000的時候介面就直接卡死了!
為啥就卡死了呢?總得有原因吧?有問題找原因!
兩個方向:
http請求 一個socket連結的建立 另一個就是檔案的讀取解釋或者編譯

socket的建立是系統級別的 所以我們首先去查系統

檢視linux核心日誌:

dmesg|tail

如圖所示 報錯了吧:
Nginx高階篇(九)單機併發1萬解決和優化方案
這錯是啥意思呢?
代理或者伺服器裝置都有埠限制,如果使用 TCP 連線,連線數量達到埠限制,在這種情況下,將不能建立新的連線。就這意思,說白了就是你的tcp連結太多啦!

現在我們再去看nginx的錯誤日誌

more /usr/local/nginx/logs/error.log

看看吧少年:
Nginx高階篇(九)單機併發1萬解決和優化方案
Too many open files:
too many open files是Linux系統中常見的錯誤,從字面意思上看就是說程式開啟的檔案數過多,不過這裡的files不單是檔案的意思,也包括開啟的通訊連結(比如socket),正在監聽的埠等等,所以有時候也可以叫做控制程式碼(handle),這個錯誤通常也可以叫做控制程式碼數超出系統限制。
引起的原因就是程式在某個時刻開啟了超過系統限制的檔案數量以及通訊連結數,通過命令

ulimit -n
```shell
more /usr/local/nginx/logs/error.log

引起的原因就是程式在某個時刻開啟了超過系統限制的檔案數量以及通訊連結數,通過命令

ulimit -n

可以檢視當前系統設定的最大控制程式碼數是多少!可以檢視當前系統設定的最大控制程式碼數是多少!

也就是說造成失敗的原因有兩個大方向
一:nginx
二:系統層面
咋辦啊?只能優化了,優化系統層面的和優化Nginx各項配置,這他媽都運維的活了,我一搞研發的我發現我研究的有點跑題了!寫吧!往下看!

系統層面優化和Nginx的配置優化使其滿足一萬併發的要求

先畫個圖 定好整體的優化方向 別瞎幾把優化 優化不好系統或者Nginx就攤了!
Nginx高階篇(九)單機併發1萬解決和優化方案
前沿:
高併發解決的前提思路是socket(tcp)連線數要頂住還有就是處理程式的時候檔案開啟的數量要頂住!這兩個有一個頂不住就不用談什麼高併發處理!這是前提條件!

socket(http請求)層面:

1.http連結快速關閉 keep_alivetime:0
先來了解一下這個http的keep-alivetime是幹哈滴
你開啟很多網站請求頭資訊會發現都有它
在http早期,每個http請求都要求開啟一個tpc socket連線,並且使用一次之後就斷開這個tcp連線。
使用keep-alive可以改善這種狀態,即在一次TCP連線中可以持續傳送多份資料而不會斷開連線。通過使用keep-alive機制,可以減少tcp連線建立次數,也意味著可以減少TIME_WAIT狀態連線,以此提高效能和提高httpd伺服器的吞吐率(更少的tcp連線意味著更少的系統核心呼叫,socket的accept()和close()呼叫)。
但是,keep-alive並不是免費的午餐,長時間的tcp連線容易導致系統資源無效佔用。配置不當的keep-alive,有時比重複利用連線帶來的損失還更大。所以,正確地設定keep-alive timeout時間非常重要。
keepalvie timeout
Httpd守護程式,一般都提供了keep-alive timeout時間設定引數。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。這個keepalive_timout時間值意味著:一個http產生的tcp連線在傳送完最後一個響應後,還需要hold住keepalive_timeout秒後,才開始關閉這個連線。
當httpd守護程式傳送完一個響應後,理應馬上主動關閉相應的tcp連線,設定 keepalive_timeout後,httpd守護程式會想說:”再等等吧,看看瀏覽器還有沒有請求過來”,這一等,便是keepalive_timeout時間。如果守護程式在這個等待的時間裡,一直沒有收到瀏覽發過來http請求,則關閉這個http連線。
重點:長時間的tcp連線容易導致系統資源無效佔用 在如此高併發的前提下如果還讓一個連線保持65s的時間簡直是大大的浪費浪費浪費,這麼多人在搶資源你還站著廁所不拉屎!所以,第一步就是來解決它:
找到Nginx的配置檔案(改成0即可 表示沒有保持時間):
Nginx高階篇(九)單機併發1萬解決和優化方案
2.子程式允許開啟的連結(worker_connections)
Nginx高階篇(九)單機併發1萬解決和優化方案
先來了解一下Nginx裡面的worker_connections是幹啥滴?
原來安裝好nginx之後,預設最大的併發數為1024,如果你的網站訪問量過大,已經遠遠超過1024這個併發數,那你就要修改worker_connecions這個值 ,這個值越大,併發數也有就大。當然,你一定要按照你自己的實際情況而定,也不能設定太大,不能讓你的CPU跑滿100%;
worker_connections程式連線數量要小於等於系統的最大開啟檔案數
Nginx高階篇(九)單機併發1萬解決和優化方案
3.設定系統最大開啟檔案數:
在2當中不都講了嗎 worker_connections程式連線數量要小於等於系統的最大開啟檔案數 我們在Nginx當中已經設定了worker_connecions 10240
給系統最大開啟檔案數來個2萬
執行命令:

ulimit -n 20000

4.設定系統的最大連結數:
先看看系統最大連結數是幹哈滴?
/proc/sys/net/core/somaxconn這個引數 linux中核心的一個不錯的引數somaxconn
對於一個TCP連線,Server與Client需要通過三次握手來建立網路連線.當三次握手成功後,
我們可以看到埠的狀態由LISTEN轉變為ESTABLISHED,接著這條鏈路上就可以開始傳送資料了.
每一個處於監聽(Listen)狀態的埠,都有自己的監聽佇列.監聽佇列的長度,與如下兩方面有關:
somaxconn引數 定義了系統中每一個埠最大的監聽佇列的長度,這是個全域性的引數,預設值為128,對於一個經常處理新連線的高負載 web服務環境來說,預設的 128 太小了!高併發情況下所以要調大!
執行命令:

echo 50000 > /proc/sys/net/core/somaxconn #50000有點猛哈 你根據自己情況來定

5.加快tcp連線的回收(recycle):
採用Nginx反向代理服務後,作業系統會產生較多TIME_WAIT的TCP(Transmission Control Protocol)連線,作業系統預設TIME_WAIT的TCP連線回收時間是2分鐘,這樣會使回收TCP過慢導致系統吞吐量下降,甚至出現502訪問失敗問題!如此大併發的場景下必須要加快tcp連結的回收!
執行命令:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle #預設為0 表示不快速回收120s後回收

6.空的tcp是否允許回收利用(reuse)
先來了解一下tcp_tw_reuse?
tcp_tw_reuse 設定允許在TIME_WAIT 狀態下重複使用一對套接字,由核心確保不會有類似於重複序列號的問題。由於兩端都使用了時間戳,所以能夠避免序列號重複。也可以基於某些關閉標識如FIN(表示不會有新的流量),來重複使用套接字。

echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse #預設為0 表示允許回收利用

7.洪水攻擊(不做洪水攻擊抵禦)
什麼是洪水攻擊?
洪水攻擊(FLOOD ATTACK)是指利用計算機網路技術向目標主機傳送大量無用的資料包文,使得目標主機忙於處理無用的資料包文而無法提供正常服務的網路行為!如果高併發,linux核心會判斷為是洪水攻擊行為,會自動為我們抵禦這種它認為是洪水攻擊的行為,其實不是!
那麼我們就要關閉這行機制!

echo 0 > /proc/sys/net/ipv4/tcp_syncookies
開啟的檔案數量層面:

nginx層面:
開啟nginx配置檔案
子程式允許開啟的檔案數量(給他10000個):
Nginx高階篇(九)單機併發1萬解決和優化方案
系統層面:
上邊講過了 隨著2開始寫的 第3個就是
執行命令:

ulimit -n 20000

測壓:

ab -n 100000 -c 5000 http://192.168.1.168/index.html

看結果:失敗次數0 你可以搞到20萬次請求1萬個併發或者更高試試
Nginx 高階篇(九)單機併發 1 萬 10 萬次請求解決和優化方案

本作品採用《CC 協議》,轉載必須註明作者和本文連結

胡軍

相關文章