بلاگ/تست بار وب‌سایت و API با k6: چطور قبل از آپگرید سرور مجازی یا اختصاصی ظرفیت واقعی را بسنجید؟
به‌روز شده

تست بار وب‌سایت و API با k6: چطور قبل از آپگرید سرور مجازی یا اختصاصی ظرفیت واقعی را بسنجید؟

1405/08/130 بازدید
تست بار وب‌سایت و API با k6: چطور قبل از آپگرید سرور مجازی یا اختصاصی ظرفیت واقعی را بسنجید؟

تست بار وب‌سایت و API با k6: چطور قبل از آپگرید سرور مجازی یا اختصاصی ظرفیت واقعی را بسنجید؟

سایت یا API شما زیر بار ترافیک بالا کند می‌شود و اولین واکنش معمول این است: «بیا پلن سرور را بالاتر ببریم». این تصمیم بدون عدد، گاهی پول اضافه‌ای است که مشکل را حل نمی‌کند، چون ممکن است گلوگاه جای دیگری باشد. k6 ابزاری است که با چند خط اسکریپت، تعداد مشخصی کاربر همزمان را روی سایت یا API شما شبیه‌سازی می‌کند و عدد واقعی ظرفیت فعلی سرور را می‌دهد.

نمایی از اجرای تست بار k6 روی یک سرور و نمودار درخواست بر ثانیه

تست بار با تست سرعت سرور مجازی فرق دارد

تست سرعت سرور مجازی معمولا یک درخواست تنها را اندازه می‌گیرد: صفحه در چند میلی‌ثانیه بار می‌شود، یا یک API چقدر طول می‌کشد تا جواب بدهد. این عدد برای کاربر اول خوب است، اما چیزی درباره رفتار سرور وقتی ۵۰ یا ۵۰۰ کاربر هم‌زمان درخواست می‌فرستند نمی‌گوید.

تست بار دقیقا همین را اندازه می‌گیرد. چند کاربر مجازی به‌طور هم‌زمان درخواست می‌فرستند و شما می‌بینید زمان پاسخ، نرخ خطا و تعداد درخواست در ثانیه چطور تغییر می‌کند. اگر قرار است پلن سرور مجازی را عوض کنید یا به یک سرور اختصاصی بروید، همین عدد است که باید تصمیم‌تان را بسازد، نه حس کلی «سایت کند شده».

k6 چیست و چرا سراغ همین ابزار برویم؟

k6 یک ابزار متن‌باز برای تست بار است که اسکریپت تست را با جاوااسکریپت می‌نویسید، اما خودش با Go کامپایل شده و با منابع کم می‌تواند هزاران درخواست در ثانیه بزند. نصبش یک باینری است، خروجی‌اش خلاصه و خوانا است و برای تست API به همان راحتی صفحه HTML کار می‌کند.

ابزارزبان اسکریپتمناسب برای
k6جاوااسکریپتوب‌سایت، REST API، تست‌های CI/CD
Apache Bench (ab)بدون اسکریپت، فقط فلگ خط فرمانیک URL ساده، تست سریع و تک‌مرحله‌ای
JMeterXML / رابط گرافیکیسناریوهای پیچیده سازمانی، اما نصب و اجرا سنگین‌تر است

برای کسی که می‌خواهد سریع یک اسکریپت بنویسد و در ترمینال یا پایپ‌لاین اجرا کند، k6 فاصله کمتری تا شروع کار دارد.

نصب k6

روی اوبونتو یا دبیان، مخزن رسمی k6 را اضافه کنید:

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
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

sudo apt-get update
sudo apt-get install k6

اگر نمی‌خواهید چیزی روی سیستم نصب کنید، نسخه داکر هم همین کار را می‌کند:

docker run --rm -v "$PWD:/scripts" grafana/k6 run /scripts/load-test.js

نصب را با یک اجرای ساده چک کنید:

k6 version

نوشتن اولین اسکریپت

یک فایل به اسم load-test.js بسازید. این نمونه یک صفحه ساده را تست می‌کند:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 20,
  duration: '30s',
};

export default function () {
  const res = http.get('https://yourdomain.com/');
  check(res, {
    'status is 200': (r) => r.status === 200,
  });
  sleep(1);
}

vus یعنی تعداد کاربر مجازی که هم‌زمان درخواست می‌فرستند و duration یعنی تست چقدر طول بکشد. تابع default همان چیزی است که هر کاربر مجازی در هر تکرار اجرا می‌کند؛ sleep(1) یک ثانیه فاصله بین درخواست‌های یک کاربر می‌گذارد تا شبیه رفتار واقعی باشد، نه یک حلقه بی‌وقفه.

برای تست API که نیاز به هدر و بدنه JSON دارد:

import http from 'k6/http';
import { check } from 'k6';

export const options = {
  vus: 10,
  duration: '20s',
};

export default function () {
  const payload = JSON.stringify({ email: 'test@example.com' });
  const params = { headers: { 'Content-Type': 'application/json' } };
  const res = http.post('https://api.yourdomain.com/v1/login', payload, params);
  check(res, {
    'status is 200 or 201': (r) => r.status === 200 || r.status === 201,
  });
}

کد اسکریپت k6 در کنار خروجی ترمینال با متریک‌های درخواست بر ثانیه

تعیین تعداد کاربر همزمان واقعی

عدد vus را از روی حدس نگذارید. اگر سایت فروشگاهی است، ببینید در ساعت پیک چند کاربر همزمان در آنالیتیکس دارید و همان را به‌عنوان نقطه شروع بگذارید. برای دیدن رفتار سرور زیر فشار فزاینده، به‌جای یک عدد ثابت، چند مرحله تعریف کنید:

export const options = {
  stages: [
    { duration: '30s', target: 20 },
    { duration: '1m', target: 100 },
    { duration: '30s', target: 200 },
    { duration: '30s', target: 0 },
  ],
};

این اسکریپت بار را از ۲۰ کاربر شروع می‌کند، کم‌کم به ۲۰۰ می‌رساند و در آخر به صفر برمی‌گردد. همین افزایش تدریجی نشان می‌دهد سرور از چه نقطه‌ای شروع به کند شدن یا خطا دادن می‌کند؛ این اطلاعات را یک تست با عدد ثابت کاربر به شما نمی‌دهد.

اجرا و خواندن خروجی

k6 run load-test.js

بعد از پایان تست، یک خلاصه در ترمینال می‌بینید. سه عدد از همه مهم‌تر است:

  • http_reqs: تعداد کل درخواست‌ها و نرخشان بر ثانیه (مثلا 1452 requests, 48.4/s). این عدد ظرفیت واقعی سرور را در لحظه تست نشان می‌دهد.
  • http_req_duration: زمان پاسخ. به‌جای میانگین، به p(95) نگاه کنید؛ یعنی ۹۵٪ درخواست‌ها سریع‌تر از این عدد جواب گرفته‌اند. میانگین می‌تواند چند درخواست کند را پنهان کند، p95 این موارد را نشان می‌دهد.
  • http_req_failed: نرخ خطا. عددی مثل 0.5% یعنی از هر ۲۰۰ درخواست، یکی با خطا یا timeout برگشته است.

برای اینکه خودتان مجبور نباشید این عددها را دستی چک کنید، آستانه تعیین کنید تا k6 خودش تست را fail کند:

export const options = {
  thresholds: {
    http_req_duration: ['p(95)<800'],
    http_req_failed: ['rate<0.01'],
  },
};

این یعنی اگر p95 از ۸۰۰ میلی‌ثانیه بیشتر شود یا بیش از ۱٪ درخواست‌ها خطا بدهند، k6 خروجی را به‌عنوان شکست علامت می‌زند؛ مناسب برای گذاشتن در پایپ‌لاین CI/CD با GitLab Runner هم هست.

از عدد تا تصمیم: کی آپگرید کنیم، کی نه؟

نتیجه تست را کنار وضعیت سرور (با top یا htop در یک ترمینال دیگر هم‌زمان با اجرای k6، یا برای دید دائمی‌تر با مانیتورینگ سرور با Prometheus و Grafana) بگذارید تا بفهمید گلوگاه کجاست:

مشاهده در نتیجه k6وضعیت سرور هم‌زمانتصمیم منطقی
p95 و نرخ خطا پایین در بار هدفCPU و RAM آرامسرور فعلی کافی است، نیازی به آپگرید نیست
p95 بالا می‌رود، نرخ خطا بالاCPU نزدیک ۱۰۰٪ یا RAM تمام شدهنیاز واقعی به منابع بیشتر؛ آپگرید پلن منطقی است
p95 بالا، اما CPU و RAM هنوز آرامدیتابیس یا کوئری کند، یا پردازش تک‌رشته‌ایمشکل از کد یا دیتابیس است، آپگرید سرور کمکی نمی‌کند
سرور زیر بار متوسط هم خطا می‌دهد یا قطع می‌شودمنابع محدود در همان سطح پایینظرفیت فعلی برای این ترافیک کم است، به سرور بزرگ‌تر یا اختصاصی نیاز دارید

اگر گلوگاه همان CPU یا RAM است و بار همزمان شما از چند ده کاربر به چند صد یا بیشتر رسیده، آپگرید از سرور مجازی به سرور اختصاصی منطقی‌تر از صرفا بالا بردن پلن می‌شود، چون منابع دیگر بین چند مشتری تقسیم نمی‌شود. برای تفاوت دقیق‌تر این دو گزینه، راهنمای انتخاب بین سرور مجازی و سرور اختصاصی را ببینید. اگر بار هنوز در محدوده چند ده کاربر همزمان است، یک پلن سرور مجازی بزرگ‌تر معمولا کافی و به‌صرفه‌تر است.

نتیجه‌گیری

قبل از تغییر پلن سرور مجازی یا رفتن سراغ سرور اختصاصی، یک تست بار ساده با k6 نشان می‌دهد مشکل از کمبود منابع است یا از جای دیگری در کد و دیتابیس. نصب سریع است، اسکریپت اول چند خط بیشتر نیست و خروجی‌اش دقیقا سه عدد کلیدی می‌دهد: درخواست بر ثانیه، تاخیر p95 و نرخ خطا. همین سه عدد پایه تصمیم‌گیری درست است، نه حدس.

اگر نتیجه تست نشان داد سرور فعلی کم می‌آورد، می‌توانید مشخصات سرورهای مجازی ابری آریانت را ببینید و پلنی متناسب با عدد واقعی بار خودتان انتخاب کنید.

سؤالات متداول

آیا تست بار با k6 می‌تواند سایت من را از کار بیندازد؟ اگر بار را از عدد پایین شروع کنید و به‌تدریج بالا ببرید، ریسک کنترل‌شده است؛ فقط تست‌های سنگین را روی سرویس تولیدی در ساعات پرترافیک اجرا نکنید.

چند کاربر همزمان برای یک تست اولیه کافی است؟ برای شروع ۱۰ تا ۲۰ کاربر مجازی کافی است؛ بعد با افزایش تدریجی مرحله‌ای ببینید سرور از چه نقطه‌ای شروع به افت می‌کند.

تفاوت p95 و میانگین زمان پاسخ چیست؟ میانگین می‌تواند چند درخواست کند را در میان بقیه پنهان کند؛ p95 نشان می‌دهد ۹۵٪ کاربران واقعی حداکثر چه زمانی را تجربه کرده‌اند.

آیا k6 فقط برای وب‌سایت است یا روی API هم کار می‌کند؟ روی هر دو کار می‌کند؛ همان تابع http.get یا http.post برای صفحه HTML و برای endpoint یک API به یک شکل استفاده می‌شود.