背景
小A:小B,最近調你的接口老是超時呀,8秒都還沒返回結果,是不是有性能問題呀!
小B :我看看~~
類似這樣的對話,在現實中是時有發生的,不是特別嚴重的話,往往大家也不會去重視這個事。
尤其是在一些測試資源並不完備的,開發人員對性能測試沒有接觸過的一些公司,遇到這些會顯得更加力不從心。
本着對自己寫出來的東西負責,上線之前,我們都應該對自己的接口進行一個簡單的壓力測試。
其實做這一步也是為了讓我們心里有個度,有個底,不至於說連能承受多少量都不知道。如果什么都不知道,那很容易陷入一個無底深淵,這是一件很可怕的事情。
老黃平時用的比較多的是Apache Bench,當然,jmeter、wrk和vegeta也都是非常不錯的。
說說用這個的原因吧,免安裝,綠色版,開箱(解壓)即用,說白了,老黃其實就是懶鬼~~
jmeter要裝jdk,懶得弄。
wrk/wrk2 要自己編譯,mac上面可以直接安裝,但是我的mac配置不高,不折騰。
vegeta用起來感覺不是很順手,后面再慢慢挖掘。
Apache Bench 介紹
Apache Bench 是Apache服務器自帶的一個web壓力測試工具,簡稱ab。
ab是一個命令行工具,對發起負載的本機要求很低,根據ab命令可以創建很多的並發訪問線程,模擬多個訪問者同時對某一URL地址進行訪問,因此可以用來測試目標服務器的負載壓力。總的來說ab工具小巧簡單,上手學習較快,可以提供需要的基本性能指標,但是沒有圖形化結果,不能監控。
ab進行的測試的本質是基於HTTP協議,可以理解為對web服務器軟件的黑盒性能測試,獲得的一切數據和計算結果,都是可以通過HTTP來解釋的。
Apache Bench 簡單使用
下面的示例都是在CentOS上面的。
通過下面的命令安裝,
yum -y install httpd-tools
裝好之后,運行一下ab -V
就可以看到版本信息。
ab -V
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
運行一下ab -h
就可以看到幫助信息。
幫助信息有很多,也比較詳細,老黃把一些常用的參數都添加了注釋,方便大家查看。
其中最常用的兩個參數是 -c
和 -n
,當然如果是POST/PUT請求的話,還離不開 -T
和 -p
。
說了不少廢話,來看看怎么使用才是重點。
下面准備了兩個簡單的接口來進行演示
[ApiController]
[Route("test")]
public class TestController : ControllerBase
{
[HttpGet]
public string Get() => "GET";
[HttpPost]
public string Post([FromBody]string value) => value;
}
這個接口是跑在docker里面的(一台2c4g的活動雲服務器),下面的圖可以看到具體的信息,還有兩個接口的訪問詳情。
先來壓一下GET請求的接口, 200並發,5000個請求。
ab -c 200 -n 5000 localhost:9000/test
POST請求有點不一樣,要先准備一下body的參數,這里在/tmp目錄創建了一個post.json
文件,里面就一個字符串。
cat /tmp/post.json
"Post"
在壓測命令里面,指定Content-Type
為application/json
, 參數的數據文件路徑是/tmp/post.json
同樣也是200並發,5000個請求。
ab -c 200 -n 5000 -T "application/json" -p /tmp/post.json localhost:9000/test
到這里,大家對怎么壓測,應該都不會太陌生了,比較陌生的應該是壓測的結果要怎么看。
下面拿其中一個結果示例來說明各項指標的含義:
Server Software: Kestrel # 服務器軟件名稱
Server Hostname: localhost # 服務器主機名
Server Port: 9000 # 服務器端口
Document Path: /test # 測試的URL路徑
Document Length: 3 bytes # 文檔大小
Concurrency Level: 200 # 並發數
Time taken for tests: 2.386 seconds # 消耗的總時間
Complete requests: 5000 # 總次數
Failed requests: 0 # 失敗的請求數
Write errors: 0 # 網絡連接寫入錯誤數
Total transferred: 680000 bytes # 傳輸的總數據量
HTML transferred: 15000 bytes # HTML文檔的總數據量
Requests per second: 2095.43 [#/sec] (mean) # (平均每秒的請求數) 這個是非常重要的參數數值,服務器的吞吐量
Time per request: 95.446 [ms] (mean) # (所有並發用戶都請求一次的平均時間)
Time per request: 0.477 [ms] (mean, across all concurrent requests) # (單個用戶請求一次的平均時間)
Transfer rate: 278.30 [Kbytes/sec] received # 每秒獲取的數據長度 (傳輸速率,單位:KB/s)
# 網絡上消耗的時間的分解
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 3.7 2 20
Processing: 12 68 120.0 53 1057
Waiting: 1 67 120.1 52 1050
Total: 15 71 119.8 55 1058
# 整個場景中所有請求的響應情況
Percentage of the requests served within a certain time (ms)
50% 55
66% 63
75% 68
80% 71
90% 77
95% 88
98% 105
99% 1012
100% 1058 (longest request)
這么多的指標,我們可以重點關注下面幾個
- Requests per second
- Failed requests
- 90%,95%和98%的響應時間
第一個是吞吐量,這個上不去,其實是挺尷尬的。
第二個是失敗的請求數,這個數要盡可能的低,最好是0,沒有失敗的。設想一下,100個請求,80個都是失敗的,這個結果還能有意義不。
第三個是響應時間,這個可以看到大部分請求的速度如何。
進行壓測時的一些小建議:
- 壓測盡可能讓並發數從低往高慢慢遞增,避免一開始就設的太大,一個比較好的參考依據是現在階段線上環境的並發數
- 壓測的持續時間可以持續久一點,這樣可以看到更多可能出現的情況,可以考慮5分鍾,8分鍾,15分鍾等
- 有條件的,壓測和被壓測的機器要獨立,因為壓測的時候也會有資源占用,可能會影響被壓測的接口
- 不要只看壓測的結果數據,還要留意被壓測機的cpu,內存等指標在壓測時是否正常
- 內網壓測的效果達到預期后,再考慮外網的,網絡因素,可控性不強
分布式壓測和全鏈路壓測,暫時不用想了,留給更專業的人去做吧~~