某測試模擬器性能優化-交叉驗證

新的問題

上一篇文章說到,重構了client_simulator組件以後,能夠模擬的客戶端並發數量有了明顯的提升。但是,這時又出現了一個新的問題,當並發數量超過300的時候,會出現發送頻率不滿足要求的情況,換句話說,並不是所有的客戶端都能每秒請求10次。經過統計,並發量越大,這種情況越嚴重。但是,此時CPU和網路資源都還沒有用滿,令人費解。

新的嘗試

一開始懷疑是進程和線程數的配比需要調整,比如增加進程數,減少每個進程上啟動的線程數,或者相反。經過嘗試,發現情況並沒有本質的改善。

考慮到線程是由操作系統調度的,即使Python代碼裡面寫time.sleep(0.09),也不能保證該線程一定在90毫秒後會被操作系統調度運行,更何況是在有幾百個這樣的線程同時運行,反覆頻繁切換的情況下。所以,我們開始懷疑是線程開銷太重,導致系統來不及切換。必須尋找一種更輕的調度模型來代替線程,這時,我們想到了golang的goroutine,據說goroutine這種協程十分輕量,可以在一個進程中執行有數以十萬計的協程,依舊保持高性能。

使用Golang驗證

考慮到client_simulator邏輯非常簡單,花了1個小時,把它用golang重寫了一遍,每個goroutine代表一個客戶端邏輯。上機一跑,感覺CPU佔用明顯比之前Python的多進程+多線程版本要少。不過,讓人鬱悶的是,golang版的client_simulator運行時同樣無法滿足客戶端要求的發送頻率,依然有很多客戶端是在2秒鐘才請求了10次。

調優進行到這一步,似乎又陷入了困境。只好再從頭捋一捋整個組件的邏輯了:客戶端請求網路數據,拿到後再請求下一次,確保1秒鐘請求10次。這個過程中,只有網路響應時間是不可控的,但是考慮到每次請求的數據量很小,又是內網環境,響應時間應該只有10毫秒左右,不應該請求不了10次啊!

慢著,這一切都只是我們的分析,現實是不是這樣的呢?我們必須驗證一下!

使用JMeter驗證

JMeter是工業級的性能測試工具,它的優勢是跨平台,容易使用。我們可以通過它的監聽器-response time graph看到它發出的請求響應時間統計結果。 使用它有如下幾步:

  • 在執行機上安裝JRE
  • 下載apache JMeter壓縮包,解壓
  • 運行JMeter,製作測試計劃
  • 在測試計劃裡面新建線程組,添加Sampler-HTTP請求。
  • 使用JMeter執行該測試計劃,生成結果文件jtl
  • 在JMeter的response time graph組件中導入結果文件jtl,生成圖表。

跑完一看,見鬼,真的有很多請求無法及時拿到數據,最長的要1秒才能完成HTTP請求。如圖。

後續

通過JMeter和Golang版的組件的交叉驗證,我們發現模擬器的性能問題是由於伺服器無法同時處理超過300個客戶端請求導致的。把這個情況和開發溝通後,開發經過調查,確認了伺服器確實存在這個問題。

通過這次調優,可見雖然分析很重要,但是實踐也必須要跟上分析的節奏。心想為虛,眼見為實。Talk is cheap, show me the data.

如果覺得本文對您有幫助,敬請點贊。

推薦閱讀:

Python進階課程筆記(四)
Scrapy爬蟲框架教程(一)-- Scrapy入門
結巴分詞獲取關鍵詞時怎麼過濾掉一些停用詞?
Python Generator漫談

TAG:Python | 自动化测试 | jmeter |