תארו לעצמכם: האפליקציה הניידת שלכם מגיעה לראש ה-App Store, ו-50,000 משתמשים חדשים מציפים אותה בין לילה. בבוקר, אתם מגלים שהשרת קרס—שגיאות 504 על כל מסך. ללא בדיקת עומסים, השרת לא יכול להתמודד עם עליות שיא מהודעות push או קמפיינים פרסומיים. אנחנו מבצעים בדיקות מחזור מלא: כתיבת סקריפטים ב-k6, JMeter או Gatling; הגדרת פרופילי עומס; ניתוח צווארי בקבוק; ומתן המלצות אופטימיזציה. k6 מריץ סקריפטים פי שלושה מהר יותר מ-JMeter בעומסים גבוהים, והסקריפטים שלו קומפקטיים וקריאים. להלן, אנו עוברים על התהליך באמצעות דוגמה טיפוסית של API למובייל.
למה בדיקת עומסים ל-API היא קריטית לאפליקציות מובייל
תעבורת מובייל שונה מתעבורת web: מכשירים שולחים בקשות במקביל, רצים ברקע, וחווים תנאי רשת בלתי צפויים. ללא פרופיל עומסים, השרת עלול לא לעמוד בעומסי שיא. בעיה נפוצה היא שהשרת מתוכנן לתעבורה ממוצעת, לא לעליות מהודעות push או קמפיינים פרסומיים.
איך אנחנו בוחרים את הכלי
שלושה כלים עיקריים, כל אחד למטרה שלו:
| כלי | שפת סקריפט | חוזק |
|---|---|---|
| k6 | JavaScript | מודרני, ידידותי ל-CI, חסם כניסה נמוך |
| JMeter | XML / GUI | בוגר, פלאגינים עשירים, עיצוב בדיקות ויזואלי |
| Gatling | Scala / DSL | מדדים מדויקים, דוחות HTML נוחים |
עבור רוב ה-APIs למובייל, אנחנו בוחרים ב-k6—סקריפטים קומפקטיים, אינטגרציה טבעית עם Grafana, רץ ב-Docker ללא JVM. המומחים שלנו (5+ שנות ניסיון) מגדירים את הכלי לארכיטקטורה שלכם.
כתיבת סקריפט k6 ל-API למובייל
ל-API טיפוסי למובייל יש מאפיינים מיוחדים: אימות JWT עם TTL קצר, refresh tokens, דחיסת תגובות gzip, לפעמים GraphQL במקום REST. הסקריפט חייב לקחת זאת בחשבון.
import http from 'k6/http';
import { check, sleep } from 'k6';
import { SharedArray } from 'k6/data';
// Тестовые аккаунты из CSV — не один аккаунт для всех VU
const users = new SharedArray('users', () => open('./test_users.csv').split('\n').map(line => {
const [email, password] = line.split(',');
return { email, password };
}));
export const options = {
stages: [
{ duration: '2m', target: 100 }, // разгон
{ duration: '5m', target: 500 }, // плато
{ duration: '2m', target: 1000 }, // пик
{ duration: '1m', target: 0 }, // спад
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% запросов < 500ms
http_req_failed: ['rate<0.01'], // менее 1% ошибок
},
};
export default function () {
const user = users[__VU % users.length];
// Логин + получение токена
const loginRes = http.post(
'https://api.example.com/v1/auth/login',
JSON.stringify({
email: user.email,
password: user.password,
}),
{
headers: {
'Content-Type': 'application/json',
},
}
);
check(loginRes, {
'login 200': (r) => r.status === 200,
'has token': (r) => r.json('data.access_token') !== undefined,
});
const token = loginRes.json('data.access_token');
sleep(1); // имитируем поведение пользователя
// Загрузка ленты
const feedRes = http.get('https://api.example.com/v1/feed?page=1&limit=20', {
headers: {
Authorization: `Bearer ${token}`,
},
});
check(feedRes, {
'feed 200': (r) => r.status === 200,
'feed has items': (r) => r.json('data.items').length > 0,
});
sleep(2);
}התיעוד הרשמי של k6 ממליץ להשתמש ב-SharedArray כדי לחלק נתוני בדיקה בין משתמשים וירטואליים.
import http from 'k6/http'; import { check, sleep } from 'k6'; import { SharedArray } from 'k6/data'; // Тестовые аккаунты из CSV — не один аккаунт для всех VU const users = new SharedArray('users', () => open('./test_users.csv').split('\n').map(line => { const [email, password] = line.split(','); return { email, password }; })); export const options = { stages: [ { duration: '2m', target: 100 }, // разгон { duration: '5m', target: 500 }, // плато { duration: '2m', target: 1000 }, // пик { duration: '1m', target: 0 }, // спад ], thresholds: { http_req_duration: ['p(95)<500'], // 95% запросов < 500ms http_req_failed: ['rate<0.01'], // менее 1% ошибок }, }; export default function () { const user = users[__VU % users.length]; // Логин + получение токена const loginRes = http.post('https://api.example.com/v1/auth/login', JSON.stringify({ email: user.email, password: user.password, }), { headers: { 'Content-Type': 'application/json' }, }); check(loginRes, { 'login 200': (r) => r.status === 200, 'has token': (r) => r.json('data.access_token') !== undefined, }); const token = loginRes.json('data.access_token'); sleep(1); // имитируем поведение пользователя // Загрузка ленты const feedRes = http.get('https://api.example.com/v1/feed?page=1&limit=20', { headers: { Authorization: `Bearer ${token}` }, }); check(feedRes, { 'feed 200': (r) => r.status === 200, 'feed has items': (r) => r.json('data.items').length > 0, }); sleep(2); } עבור משתמשים הוא קריטי. אם כל המשתמשים הווירטואליים חולקים חשבון אחד, השרת עלול לשמור את הסשן במטמון, ולעוות את התוצאות.
אילו פרופילי עומס נדרשים?
תעבורת מובייל אינה אחידה. אנו מגדירים ארבעה פרופילים טיפוסיים:
פרטים על פרופילי עומס
| פרופיל | מטרה | משך | קריטריוני הצלחה |
|---|---|---|---|
| בסיסי | פעולה יציבה 24/7 | 1–2 שעות | p95 < 300 ms, שיעור שגיאות < 0.1% |
| שיא | עלייה בבוקר/ערב | 30 דקות | p95 < 500 ms, שיעור שגיאות < 1% |
| מתח | מציאת נקודת שבירה | 10–20 דקות | שיעור שגיאות < 5% |
| השריה | זיהוי דליפות | 4–8 שעות | השהיה לא גדלה |
בסיסי—עומס קבוע 24/7. בודק שבתעבורה ממוצעת p95 < 300 ms. שיא—עליות בבוקר ובערב. עלייה הדרגתית מ-10% ל-300% מהממוצע תוך 5 דקות.
מתח—חריגה מכוונת מהמקסימום המשוער כדי למצוא את נקודת השבירה. המשך עד ששיעור השגיאות עולה על 5% או שהשהיה גדלה פי עשרה.
השריה—70% מהשיא למשך 4–8 שעות. תופס דליפות זיכרון, דלדול מאגר חיבורי מסד נתונים, בעיות רוטציית לוגים.
ניתוח תוצאות: למה לשים לב במדדים
k6 שולח מדדים ל-Grafana דרך InfluxDB או כתיבה מרחוק מובנית של Prometheus:
k6 run --out influxdb=http://localhost:8086/k6 scenario.js לאחר הריצה, בדקו:
-
SharedArrayאחוזונים (p50, p90, p95, p99) -
k6 run --out influxdb=http://localhost:8086/k6 scenario.js—זמן תור (ערך גבוה = מאגר חיבורים מדולדל) -
http_req_duration—זמן חיבור TCP (גבוה = אין keep-alive) -
http_req_blocked—נפח נתונים (גדול במפתיע = אין gzip או שדות מיותרים בתגובה)
צווארי בקבוק טיפוסיים ב-API למובייל:
- שאילתות N+1 למסד נתונים בעת טעינת פיד עם אובייקטים מקוננים
- אינדקס חסר על
http_req_connecting+data_receivedבטבלת הפוסטים - שליחת הודעות push סינכרונית בתוך הבקשה במקום תור רקע
ריצה ב-CI
---
- name: Run k6 load test
uses: grafana/[email protected]
with:
filename: tests/load/api_test.js
flags: --duration 5m --vus 100
env:
K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}
---ב-CI אנו מריצים פרופיל קל (100 VUs, 5 דקות) לבדיקת רגרסיה בסיסית בביצועים. בדיקות מתח מלאות מתוזמנות או מופעלות לפני שחרורים.
מה כלול בעבודה שלנו
אנו מספקים חבילה מלאה:
- סקריפטים לבדיקת עומסים מוכנים (k6/JMeter/Gatling)
- דוח עם מדדים וגרפים (לוח מחוונים של Grafana)
- המלצות לאופטימיזציה של צווארי בקבוק
- אינטגרציה ל-CI/CD שלכם (GitHub Actions, GitLab CI, Jenkins)
- ייעוץ עם צוות השרת שלכם על התוצאות
- אחריות לתקינות הסקריפט: עיבוד חוזר בחינם אם השרת משתנה
איך לכתוב סקריפט k6: מדריך שלב אחר שלב
- הכינו נתוני בדיקה. צרו קובץ CSV עם חשבונות משתמשים (אימייל, סיסמה)—לפחות 100 רשומות.
- צרו סקריפט. ייבאו מודולי k6, הגדירו אפשרויות (שלבים, thresholds), ואת הפונקציה הראשית עם אימות ובקשות טיפוסיות.
- הגדירו סביבה. התקינו k6 מקומית או ב-Docker, הכינו InfluxDB/Grafana לאיסוף מדדים.
- הריצו בדיקה. בצעו
user_idעם הפרמטרים הרצויים. - נתחו תוצאות. עיינו בלוחות המחוונים, זהו צווארי בקבוק.
ניסיון החברה
יש לנו מעל 5 שנות ניסיון בבדיקות עומסים וביצענו יותר מ-50 פרויקטים עבור אפליקציות פינטק, מסחר אלקטרוני ומדיה חברתית. מומחים מוסמכים ב-k6 ו-JMeter מבטיחים תוצאות אובייקטיביות.
לוחות זמנים ועלות
לוחות זמנים משוערים: 3–7 ימים לפיתוח סקריפטים, ביצוע ודיווח. חיסכון בתשתיות לאחר האופטימיזציה שלנו יכול להגיע ל-40%. העלות נקבעת לאחר עיון בתיעוד ה-API שלכם.
צרו קשר לייעוץ—נעריך את הפרויקט שלכם. הזמינו בדיקת עומסים כדי למנוע השבתה ואובדן משתמשים.







