運維攻堅之jmeter壓力測試報錯

wls1036發表於2021-07-30

背景

某客戶實施DAP,在上線前需要對DAP進行壓力測試,有專門的壓力測試環境,並且要求併發能夠達到1000,團隊使用jmeter作為壓測工具,整個系統架構很簡單瀏覽器->Nginx->Tomcat,在壓測的時候碰到以下問題

  • 對DAP流程提交介面進行壓測,壓測不透過
  • 部署一個僅僅返回請求引數,沒有任何業務邏輯,壓測不透過
  • 繞過Nginx,直接對Tomcat進行壓測,壓測透過
  • 直接對Nginx進行壓測,壓測Nginx welcome頁面,壓測不透過

並且對Nginx進行了大量的調優,能調的引數基本都試過,壓測不透過,總結下來就是,只要經過Nginx,壓測就不透過,看來問題出現在Nginx上

環境資訊

  • Nginx:16CPU 64G記憶體
  • Nginx配置,這裡只列幾個比較重要的引數
worker_processes 16;
worker_connections 1000;
keepalive_timeout 60;

這些引數都調整過,對結果影響不大,當然如果調的太極端,比如worker_processes設定為1,肯定是會報錯的。

  • Tomcat:16CPU 64G記憶體

這個配置Nginx跑1000併發完全是足夠的

排查

先看下兩個測試結果對比

  • 壓測tomcat簡單介面,併發1000,迴圈50次,總共50000次請求

壓測結果

所有請求沒有出現Error

  • 壓測Nginx welcome頁面,併發1000,迴圈50次,總共50000次請求

有百分之0.31%的錯誤率,雖然不高,但這個錯誤率是一直有的,而且如果說Nginx的壓測不如Tomcat,相信這個結果大家都接受不了,Nginx是負載均衡產品中公認最強的產品,一個是負載均衡,一個是應用伺服器,負載均衡最重要的就是併發能力,應用伺服器最重要的是業務能力,如果Tomcat在併發能力上超過Nginx,可能會顛覆很多人的認知。所以這其中肯定是有問題的。

Nginx壓測請求的錯誤主要集中在以下幾點

  • java.net.ConnectionException: Connection refused: connect
  • java.net.SocketException: Connection reset
  • java.net.SocketException: Unexpected end of file from server
  • org.apache.http.NoHttpResponseException: failed to respond

基本上是網路錯誤,為了排除網路錯誤,做了兩個測試

本地執行

我自己電腦(MAC)開nginx和tomcat,用jmeter進行壓測,結果更不理想,也是1000併發

雖然有這麼高的錯誤率,但是不管是nginx還是tomcat,並沒有報錯,這能說明什麼問題呢,說明很可能是核心層面就報錯了,也就是請求根本就沒進來

Linux主機執行

Jmeter支援在LInux下執行,也支援命令列模式,因此可以考慮在內網伺服器找一臺同網段主機作為壓測機器,步驟如下

  • 將jmeter安裝包上傳到Linux壓測機並解壓
  • 在本地配好測試計劃,儲存為jmx檔案,並將jmx檔案上傳至Linux壓測機
  • 執行以下命令以命令列模式開啟壓測
apache-jmeter-5.4.1/bin/jmeter.sh -n -t plan.jmx -l plan.jtl

  • 將結果檔案plan.jtl下載到本地,在彙總報告中點選Browser開啟檔案

錯誤率為0,結合本地執行的結果,可以猜測跟壓測機的環境有關。

壓測機

本次使用的壓測機是一臺windows 7主機,如果是壓測機的原因,那麼為什麼壓tomcat就沒問題,壓nginx就有問題,兩次壓測到底區別在哪,我們可以用wireshark進行抓包,看兩次壓測在網路包上有什麼不同

  • Nginx壓測抓包,發現有大量RST的包,並且持續快速出現

RST是連線關閉時會傳送的資料包
  • Tomcat壓測抓包也有RST的包,但是速度明顯較慢,而且數量不多

也就是說,Nginx壓測不斷在建立連線和關閉連線,tomact建立連線和關閉連線動作並沒有那麼頻繁,我們可以在windows上用以下命令檢視連線情況

netstat -a | find /i /c "TIME_WAIT"
該命令可以統計當前系統處於TIME_WAIT狀態的連線數,TIME_WAIT表示連線處於即將關閉的狀態,這時候連線所佔用的埠依然無法釋放,無法進行再次分配,如果短時間內產生大量的TIME_WAIT連線,容易導致埠號耗盡以至於無法建立新的連線,服務無法響應
  • Tomcat壓測 TIME_WAIT連線數情況

TIME_WAIT表示等待關閉的連線數,可以看到緩慢增長,並且達到兩千左右停止增長

  • Nginx壓測TIME_WAIT連線數情況

可以看到快速增長,並且總數可以達到2w以上,最多可以達到4w,所以兩次壓測的區別就是TIME_WAIT的數量, 那為什麼會產生這種結果,以下是我的個人猜測

nginx採用的是epoll非阻塞模型,tomcat採用的是執行緒模型,一個請求一個執行緒,屬於阻塞模型,所以nginx可以段時間內"吃掉"大量的連線,tomcat需要排隊進入,這樣就造成了以上現象,nginx短時間建立大量連線,tomcat則是緩慢增加連線

結論

windows作為壓測機進行高併發壓測並不合適,因為會在短時間內產生大量連線,windows作為工作PC,在這方面處理能力不如Linux,加上網路波動等因素,容易造成錯誤,造成壓測結果失真,雖然可以透過最佳化部分引數降低錯誤率,但解決不了根本問題,建議透過同網段Linux主機作為壓測機,測試計劃可以在windows進行配置,結果分析也可以在windows中完成,但執行測試任務建議在Linux主機上進行。

相關文章