為什麼需要負載測試?
- 驗證系統在預期 QPS 下的穩定性(不 OOM、不死鎖、不超時)。
- 找出效能瓶頸:CPU、記憶體、磁碟 I/O、網路、資料庫連線池、鎖競爭。
- 為容量規劃提供數據依據(何時擴容、擴多少)。
- 回歸測試:每次發布前跑基準,防止效能退化。
ApacheBench (ab) 快速上手
# 基本語法
ab -n 總請求數 -c 併發數 [選項] URL
# 例:1000 請求,50 併發,Keep-Alive,POST JSON
ab -n 1000 -c 50 -k -p post.json -T 'application/json' https://api.example.com/users
常用參數速查
| 參數 | 含義 | 建議 |
-n | 總請求數 | ≥ 1000,視 QPS 目標調整 |
-c | 併發數 | 從 10 遞增至目標 2-3 倍 |
-k | 啟用 Keep-Alive | 生產環境通常開啟,必加 |
-H | 自定 Header | -H 'Authorization: Bearer xxx' |
-p | POST 資料檔案 | 需搭配 -T |
-T | Content-Type | application/json 等 |
-t | 最大測試秒數 | 防止失控,如 -t 60 |
-r | 遇錯不退出 | 壓測建議加上 |
解讀輸出指標
Server Software: Apache/2.4.41
Server Hostname: api.example.com
Server Port: 443
SSL/TLS Protocol: TLSv1.2
Document Path: /api/users
Document Length: 1234 bytes
Concurrency Level: 50
Time taken for tests: 8.794 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1,754,000 bytes
HTML transferred: 1,311,000 bytes
Requests per second: 113.71 [#/sec] (mean) ← 核心吞吐指標
Time per request: 439.67 [ms] (mean) ← 平均延遲(含併發)
Time per request: 8.79 [ms] (mean, across all concurrent requests)
Transfer rate: 199.45 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.5 0 5
Processing: 111 427 123.4 410 550
Waiting: 105 410 120.1 395 540
Total: 111 427 123.4 410 555
Percentage of the requests served within a certain time (ms)
50% 410
66% 425
75% 440
80% 450
90% 480
95% 510
98% 540
99% 550
100% 555 (longest request)
關鍵指標解讀
- Requests per second (RPS):系統吞吐上限。對比目標 QPS,留 30-50% 紅利。
- Time per request (mean, across all concurrent):單請求平均處理時間 =
總耗時 / 總請求數。真實延遲參考。
- Percentiles (P50/P90/P99):長尾延遲決定用戶體驗。P99 < 500ms 為常見 SLA。
- Failed requests:非 2xx、連線重置、超時。>0% 需排查日誌。
- Connection Times → Processing:後端處理耗時。若佔比高 → 應用層優化;若 Connect 高 → 網路/負載均衡器問題。
系統參數調優閉環
- 基準測試:記錄預設配置下的 RPS、P99。
- 單一變數調整:每次只改一項(PHP-FPM pm.max_children、Nginx worker_processes、MySQL innodb_buffer_pool、Redis maxclients)。
- 重跑 ab:對比指標變化。
- 觀察系統資源:
htop、iostat -x 1、netstat -antp、pmap -x PID、perf top。
- 鎖定最佳配置:在穩定性與吞吐平衡點定版。
PHP-FPM 關鍵參數
; pool.d/www.conf
pm = dynamic
pm.max_children = 200 # 最大進程數 = (總記憶體 - 系統保留) / 單進程記憶體
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500 # 防記憶體洩漏,定期重生成
request_terminate_timeout = 30s
Nginx 關鍵參數
worker_processes auto; # = CPU 核心數
worker_connections 4096; # 單進程最大連接
keepalive_timeout 65;
client_max_body_size 10m;
open_file_cache max=10000 inactive=30s;
進階壓測工具對比
| 工具 | 特點 | 適用場景 |
| ab | 輕量、單機、HTTP/1.1、無腳本 | 快速基準、CI 門檻 |
| wrk | 多執行緒、Lua 腳本、高吞吐 | 精準壓測、複雜請求邏輯 |
| locust | Python、分散式、Web UI、腳本化 | 長時穩定性、多場景混合 |
| k6 | Go、JS 腳本、CI/CD 原生、Prometheus 整合 | 現代 DevOps、GitLab/GitHub Actions |
| JMeter | GUI、多協議、重、企業級 | 複雜業務流程、非技術人員 |
常見坑與避雷
- ab 壓測機成瓶頸:單機 ab 受限於檔案描述符、埠口、CPU。解決:多機分散式壓測(locust/k6)、調大
ulimit -n、使用 tw_reuse。
- 目標服務未預熱:JIT、OpCache、資料庫緩存、連線池需預熱後再測。
- 忽略 GC/GC 停頓:PHP 7+ GC 影響較小,但長跑觀察
gc_collect_cycles() 影響。
- 只看平均值:P99 才是 SLA,平均值掩蓋長尾。
原文《PHP程序加速探索之服務器負載測試》重構,補充 ab 參數詳解、指標深度解讀、PHP-FPM/Nginx 調優閉環、現代壓測工具對比與避雷指南。