回到昨天的題目,我們只模擬尖峰時段,大量的購物車加入商品的測試場景,但實際運行環境上,可能會不同的使用者做著不同的事情:購買商品、搜尋商品、加入到購物車、移除商品到購物車、結帳和付款等等。就像《火影忍者》裡的「影分身之術」吧!當主角鳴人同時分出數十個影分身,每個分身都在做不同的事:戰鬥、學習、探查,這就像我們的系統在面對多任務負載時的挑戰!
模擬一個視訊串流平台的高負載場景,並測試系統在同時進行多任務操作(如影片上傳、即時觀看、評論、搜尋)的情況下,是否能保持系統穩定。
挑戰設計測試場景:
graph LR
A[Load Balancer] --> B[Web Servers]
B --> C[Media Servers]
C --> D[Content Delivery Network]
B --> E[Cache Layer]
C --> F[Database Cluster]
HTTP 方法 | API 路徑 | 描述 |
---|---|---|
GET | /videos | 取得影片列表 |
GET | /videos/{videoId} | 取得指定影片的詳細資訊 |
POST | /videos | 上傳影片 |
PUT | /videos/{videoId} | 更新指定影片的資訊 |
DELETE | /videos/{videoId} | 刪除指定影片 |
GET | /videos/{videoId}/comments | 取得指定影片的評論列表 |
POST | /videos/{videoId}/comments | 新增評論至指定影片 |
GET | /search?query={keyword} | 根據關鍵字搜尋影片 |
影片卡頓問題:尖峰時段(例如同時 100 萬使用者觀看)導致媒體伺服器資源耗盡,出現影片卡頓或播放中斷。
CDN (Content Delivery Network) 部署範圍問題:全球用戶使用不同網路時,因 CDN 節點不足或頻寬不足,部分用戶播放體驗不佳。
快取層 (Cache Layer) 設計不足:熱門影片未能及時在快取內,造成影片載入時間過長。
透過上面的資訊和步驟可以設計出測試情境,以下針對場景 1 所設計出來的測試情境。而這樣的測試叫做混合工作負載測試 (Mixed workload testing)
對一個系統進行多種不同類型的工作負載測試,這些工作可能包含讀取、寫入、資料處理或是網路請求等操作,透過模擬實際環境的不同需求,這種測試方法主要是測試執行不同類型的工作負在下系統的表現,並且確保系統能夠在這樣混合的情境下保持穩定和正常運作。
指標類別 | 描述 | 數值範圍 |
---|---|---|
吞吐量 (Throughput) | 系統每秒處理的請求數或資料量。 | |
影片觀看請求 (80 萬用戶) | 每秒觀看請求數應在此範圍內 | 80,000~100,000 reqs/s |
影片上傳請求 (10 萬用戶) | 每秒上傳請求數應在此範圍內 | 10,000~20,000 reqs/s |
同時觀看和上傳請求 | 每秒同時觀看和上傳請求數應在此範圍內 | 10,000~15,000 reqs/s |
回應時間 (Response Time) | 系統回應時間 | |
影片觀看請求 | 每秒觀看請求應在此範圍內完成 | 1~2 秒 |
影片上傳請求 | 每秒上傳請求應在此範圍內完成 | 2~5 秒 |
混合觀看和上傳請求 | 同時進行觀看和上傳操作,回應時間應保持此範圍 | 1~3 秒 |
同時使用者數量 (Concurrent Users) | 系統同時支援的最大用戶數 | |
影片觀看 | 進行觀看的用戶數 | 80 萬 |
影片上傳 | 進行上傳的用戶數 | 10 萬 |
混合操作 | 同時進行觀看和上傳的用戶數 | 10 萬 |
系統資源利用率 (Resource Utilization) | 系統資源使用情況,避免過載 | |
CPU 使用率 | 保持在此範圍內,避免過高導致過載 | 70%~85% |
記憶體使用率 | 保持在此範圍內,避免記憶體不足 | 60%~80% |
磁碟 I/O 使用率 | 保持在此範圍內,避免磁碟瓶頸 | 70%~85% |
網路頻寬使用率 | 保持在此範圍內,避免頻寬瓶頸 | 60%~80% |
錯誤率 (Error Rate) | 系統操作的失敗率 | |
影片觀看失敗 | 觀看失敗率應少於此數值 | < 0.5% |
影片上傳失敗 | 上傳失敗率應少於此數值 | < 1% |
影片流暢度 (Buffering Time) | 網路頻寬增長時,影片緩衝時間應保持此範圍 | 0.5~1 秒 |
資料庫性能 (Database Performance) | 讀寫查詢的處理時間 | |
讀取查詢 | 讀取應保持在此範圍內完成 | < 100ms |
寫入查詢 | 寫入應保持在此範圍內完成 | < 200ms |
延遲 (Latency) | 系統整體延遲,確保影片觀看和上傳的流暢性 | < 100ms |
接著使用 K6 工具撰寫對應的測試腳本:這個腳本的目的是模擬 80 萬用戶觀看影片、10 萬用戶上傳影片,還有 10 萬用戶同時觀看和上傳影片,來測試系統在高負載下的效能。腳本分成不同的階段來模擬這些情境,並監控每秒的請求數和回應時間。
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 800000 }, // 80 萬觀看影片的用戶
{ duration: '30s', target: 100000 }, // 10 萬上傳影片的用戶
{ duration: '30s', target: 100000 }, // 10 萬同時觀看和上傳影片的用戶
{ duration: '1m', target: 0 }, // 快速降載至 0
],
thresholds: {
'http_req_duration': ['p(95)<2000'], // 95% 的請求必須在 2 秒內完成
'http_reqs': ['rate>100000'], // 每秒請求數需超過 10 萬
},
};
export default function () {
const userType = Math.floor(Math.random() * 3); // 隨機選擇行為:觀看、上傳或同時進行
if (userType === 0) {
// 模擬 觀看影片
const res = http.get('http://localhost:3333/videos');
check(res, {
'response time < 2s': (r) => r.timings.duration < 2000,
'status is 200': (r) => r.status === 200,
});
} else if (userType === 1) {
// 模擬 上傳影片
const res = http.post('http://localhost:3333/videos', { title: 'New Video', description: 'Test Video' });
check(res, {
'response time < 2s': (r) => r.timings.duration < 2000,
'status is 200': (r) => r.status === 200,
});
} else {
// 模擬 同時觀看和上傳影片
const viewRes = http.get('http://localhost:3333/videos');
check(viewRes, {
'response time < 2s': (r) => r.timings.duration < 2000,
'status is 200': (r) => r.status === 200,
});
const uploadRes = http.post('http://localhost:3333/videos', { title: 'New Video', description: 'Test Video' });
check(uploadRes, {
'response time < 2s': (r) => r.timings.duration < 2000,
'status is 200': (r) => r.status === 200,
});
}
sleep(1);
}
如果想要進一步挑戰,可以試著自己分析場景 2 和場景 3,並按照我們上面提到的步驟來設計和撰寫對應的測試場景與測試腳本。此外,試著找出上面測試腳本設定中的一些不合理之處,思考哪些地方可以進行調整或優化,這也是非常好的練習喔!
在這次的效能測試中,我們模擬了多種情境,包括大規模用戶同時觀看、上傳影片,以及同時進行兩者的操作。透過這些測試場景,我們能夠及早發現系統在高負載下的潛在瓶頸,像是影片加載時間過長或上傳速度變慢等問題,讓我們在真正面對高流量時能更從容應對,並且不管今天是週幾,都值得放鬆一下,繼續前進!讓我們期待下次的挑戰,隨時保持最佳狀態!