Coding Gun

หัดทำ Load Test ด้วย K6

K6 คือ Load Testing Tool อีกตัวที่มาแรงมากๆในช่วยนี้เนื่องจากสามารถสร้าง Load ด้วยการเขียน JavaScript ซึ่งง่ายต่อการทำความเข้าใจ(โดยเฉพาะ Developer) ใช้งานง่ายไม่ยุ่งยาก แถมกิน Resource น้อย และที่สำคัญคือ k6 พัฒนาจาก GrafanaLabs ซึ่งทำให้เชื่อมต่อกับ Grafana ซึ่งเป็น Monitoring Dashboard อันดับต้นๆ ได้ง่าย

การติดตั้ง K6

การติดตั้ง K6 ก็ทำได้ง่ายมากๆ ขึ้นอยู่กับ OS ที่เราใช้งานอยู่โดยมีวิธีติดตั้ง K6 ในแต่ละ Platform ดังนี้

วิธีติดตั้ง K6 บน MacOS

การติดตั้งบน MacOS นั้นเราจะใช้ Homebrew ซึ่งถ้ามี Homebrew อยู่ในเครื่องอยู่แล้วสามารถใช้ brew install ได้เลย

brew install k6

วิธีติดตั้ง K6 บน Windows

บน Windows นั้นเราสามารถใช้ได้ทั้ง winget หรือ choco

choco install k6

ซึ่งถ้าไม่ได้ติดตั้ง Choco ไว้ในเครื่องเราจะใช้ winget ในการติดต้ัง

winget install k6 --source winget

วิธีติดตั้ง K6 บน Linux

บน Linux เราจะต้อง Download PGP Key ก่อนโดยใช้คำสั่ง

sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69

เมื่อได้ K6 Key มาเรียบร้อยเราก็จะเพิ่ม URL ที่ใช้ Download K6 เข้าไปใน Source List

echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list

หลังจากนั้นให้ทำการ Update และ Install K6 ได้เลย

sudo apt-get update
sudo apt-get install k6

วิธีใช้งาน K6 ผ่าน Docker

ถ้าเราต้องการใช้งานหลายๆ Version หรืออยากได้วิธีที่สามารถนำไปใช้ได้ทุก Platform เราจะเลือก Docker โดยเราจะใช้ Image ชื่อ grafana/k6

docker pull grafana/k6

ตอนที่เรา Run load testing script เราจะโยนเข้าไปเป็น Parameter ดังนี้

docker run -i grafana/k6 run - < load-test.js

เขียน Load Testing Script

การเขียน Load testing script โดยเริ่มจากการสร้างไฟล์ load-test.js ขึ้มาและใส่เนื้อหาต่างๆ เข้าไปดังนี้

ระบุ Application ที่ต้องการทำ Load Test

เราจะระบุ URL ของ Applicaton ที่ต้องการทดสอบรวมทั้งการ Delay ด้วยตัวอย่าง code ต่อไปนี้

1
2
3
4
5
6
7
import http from 'k6/http';
import { sleep } from 'k6';

export default function () {
  const res = http.get('https://test-api.k6.io/public/crocodiles/');
  sleep(1); // Delay 1 วินาที
}

เมื่อต้องการทดสอบเราจะใช้คำสั่ง

k6 run load-test.js

2 ระบุจำนวนผู้ใช้ (VU)

ในขั้นตอนต่อไปเราจะสร้าง Load ด้วยการจำลอง จำนวนผู้ใช้งาน(VU) และระยะเวลา(Duration) ดังนี้

k6 run --vus 10 --duration 30s load-test.js

ในตัวอย่างนี้จะเป็นการจำลองผู้ใช้จำนวน 10 คนเข้าใช้งานพร้อมกันเป็นเวลา 30 วินาที ซึ่งนอกจากการใส่เข้าไปเป็น parameters ใน Command Line แล้วเรายังสามารถระบุ Options ลงไปใน Load testing script(load-test.js) ได้ดังนี้

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import http from 'k6/http';
import { sleep } from 'k6';

export const options = {
     duration: '30s', 
     target: 10 
};

export default function () {
  const res = http.get('https://test-api.k6.io/public/crocodiles/');
  sleep(1); // Delay 1 วินาที
}

หลังจากน้ันเราจะ Run load test ด้วยคำสั่ง

k6 run load-test.js

3. ตรวจสอบผลลัพธ์

Check

เป้าหมายของการทำ Load Test คือการยืนยันว่าระบบของเราสามารถรองรับการเข้าใช้งานของ Users หลายๆคนได้ ซึ่งเราต้องใช้ check เพื่อตรวจสอบผลลัพธ์และยืนยันว่าระบบยังคงสามารถทำงานได้อย่างถูกต้อง

1
2
3
4
5
6
7
export default function () {
  const res = http.get('https://test-api.k6.io/public/crocodiles/');
  check(res, { 
    'Status Code id 200' : (r) => r.status === 200 
  })
  sleep(1); // Delay 1 วินาที เพื่อให้ใกล้เคียงกับการทำงานของ Application จริงๆ
}

ในตัวอย่างนี้เราจะตรวจสอบว่า Response ที่ีเราได้กลับมาจาก Server นั้นเป็น 200 หรือไม่เท่านั้นซึ่งในการทำงานจริงอาจต้องมีการ check เพิ่มเติมว่าผลลัพธ์ HTML หรือ JSON ที่ได้รับกลับมาถูกต้องหรือไม่

Thresholds

นอกจากการใช้ check ในการตรวจสอบผลลัพธ์แล้ว เรายังสามารถใช้ Thresholds ในการระบุเงื่อนไขของการ Success หรือ Fail ได้อีกเช่น

1
2
3
4
5
6
7
8
export const options = {
    duration: '30s', 
    target: 10 
    thresholds: {
        http_req_failed: ['rate<0.01'], // ต้อง Success 99%
        http_req_duration: ['p(95)<200'], // Percentile ที่ 95 ต้องตำว่า 200 ms
    },
};

ในตัวอย่างนี้ในบรรทัดที่ 5 เราจะกำหนดว่า Request ที่ส่งไปจะสามารถ Fail ได้ 1%(ไม่จำเป็นต้อง Success ทุก Request) และในบรรทัดที่ 6 มี Response time ที่เกิน 200ms ได้ 5 Requests(Percentile ที่ 95)

Stages(Ramp Up/Ramp Down)

การทำ Load test สามารถแยกเป็นการทดสอบได้หลายรูปแบบ ขึ้นอยู่กับเป้าหมายของการทดสอบนั้นๆ เช่นถ้าคุณต้องการทำการยิง Load เข้าไปนานๆ เพื่อให้แน่ใจว่าระบบสามารถรองรับ Load ได้นานพอ แบบนี้เราจะเรียกว่าการทำ Endurance Test

ซึ่งการเพิ่มหรือลดปริมาณ Load ที่ส่งเข้าไป(Ramp Up/Ramp Down) ได้ด้วย Stages

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import http from 'k6/http';
import { sleep } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 10 }, // เพิ่มผู้ใช้ถึง 10 คนใน 30 วิ
    { duration: '3hr', target: 10 },  // คงไว้ 3 ชั่วโมง
    { duration: '30s', target: 0 },  // ลดลงเหลือ 0 ใน 30 วิ
  ],
};

export default function () {
  http.get('https://test-api.k6.io/public/crocodiles/');
  sleep(1);
}

หลังจากนั้นก็ Run ด้วยคำสั่ง

k6 run endurance-test.js

Data-driven Test

นอกจากการยิง Load ที่หน้าตาเหมือนๆกันตลอดเวลาแล้วเรายังสามารถนำเข้าข้อมูลจากไฟล์ CSV หรือ JSON เพื่อให้ได้ข้อมูลที่มีความเหมือนจริงมากขึ้น ยกตัวอย่างเช่น

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import http from 'k6/http';
import { sleep } from 'k6';
import { SharedArray } from 'k6/data';

const users = new SharedArray('users', function() {
  return JSON.parse(open('./users.json'));
});

export default function () {
  const user = users[Math.floor(Math.random() * users.length)];
  http.post('https://example.com/login', JSON.stringify(user), {
    headers: { 'Content-Type': 'application/json' },
  });
  sleep(1);
}

ตัวอย่างข้อมูลใน users.json

[
  {"username": "user1", "password": "pass1"},
  {"username": "user2", "password": "pass2"}
]

K6 Report

เราสามารนำผลลัพธ์ออกมาได้ด้วยวิธีต่างๆดังนี้

k6 run --out influxdb=http://localhost:8086/myk6db load-test.js
npm install -g k6-reporter
k6 run --out json=output.json test.js
k6-reporter output.json result.html

ตัวอย่างของ K6 Report จะเป็นดังรูป

K6 Load testing report
ตัวอย่างผลลัพธ์จากการทำ Load test ด้วย K6

Phanupong Permpimol
Follow me