בדיקות עומס רציפות בצנרת CI/CD

כל פריסה לסביבת ייצור טומנת בחובה סיכון של ירידה שקטה בביצועים, שעלולה להבריח משתמשים למתחרים. אנו משלבים בדיקות עומס רציפות ישירות בצנרת ה-CI/CD שלכם כדי לתפוס רגרסיות לפני שהן מגיעות ל-master. הצוות שלנו מספק את הפרויקט במפתח מלא, תוך הבטחת פעילות אמינה ותמיכה שוטפת.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
בדיקות עומס רציפות בצנרת CI/CD
בינוני
~3-5 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1502
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1344
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1052
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1307
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1049
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1033

בדיקות עומס רציפות בצנרת CI/CD

עם כל פריסה לייצור, הסיכון להחדרת רגרסיית ביצועים גבוה. שאילתת SQL אחת לא אופטימלית או בעיית N+1 שנשכחה יכולה להגדיל את זמן התגובה ב-50%, ומשתמשים יעברו למתחרים. אנו משלבים בדיקות עומס אוטומטיות ישירות בצנרת ה-CI/CD שלך כדי לתפוס רגרסיות כאלה לפני שהן מגיעות ל-master. התוצאה: אתה בטוח שכל commit לא שובר את ה-SLA עבור זמן אחזור ותפוקה.

אנו מגדירים בדיקות עשן עם ערכי סף שהופכים את הצנרת לשומר סף: אם זמן האחזור p95 חורג מ-500ms או שיעור השגיאות חורג מ-1%, הצנרת נכשלת והמפתח מקבל הודעה. זו לא תחליף לבדיקות עומס בקנה מידה מלא, אלא אמצעי הגנה מהיר.

בעיות שאנו פותרים

  • רגרסיית ביצועים לאחר פריסה — אפילו שינוי מיקרו בקוד יכול להאט נקודת קצה קריטית. ללא בדיקות אוטומטיות, אתה לומד על הבעיה רק לאחר תלונות משתמשים או התראות ניטור. אנו מגדירים השוואת בסיס: כל בדיקה רצה מול הענף היציב, ואם הסטייה >20%, הצנרת נחסמת.
  • שאילתות לא יעילות וצווארי בקבוק — הסקריפטים שלנו מחקים תרחישי משתמש טיפוסיים (רשימה, יצירת פוסט, חיפוש). אם שאילתה מתחילה לקחת יותר זמן, אנו רואים זאת בתרשימי המדדים.
  • חוסר תרבות של ביצועים תחילה — מפתחים לעתים קרובות לא חושבים על ביצועים במהלך סקירת קוד. בדיקות עומס רציפות הופכות את הביצועים לגלויים: כל PR מלווה בתגובה עם תוצאות בדיקה (p95, שיעור שגיאות).

כלים ומקומם ב-CI

k6 הוא הבחירה הטובה ביותר עבור CI: סקריפטים ב-JS, סטטיסטיקות מובנות, pass/fail מבוסס סף, אינטגרציה טבעית עם GitHub Actions ו-GitLab CI. עוד בתיעוד k6.

Artillery — תצורת YAML, נוחה לתיאור תרחישים ללא קוד. Gatling — Scala/Java, דוחות HTML מפורטים, נוחה לצוותי Java.

סקריפט k6 בסיסי

// tests/performance/api-smoke.js
import http from 'k6/http'
import { check, sleep } from 'k6'
import { Rate, Trend } from 'k6/metrics'

// Кастомные метрики
const errorRate = new Rate('errors')
const postCreateDuration = new Trend('post_create_duration')

export const options = {
  // Профиль нагрузки для CI: быстро, не разрушительно
  stages: [
    { duration: '30s', target: 10 }, // разогрев
    { duration: '1m', target: 10 }, // устойчивая нагрузка
    { duration: '10s', target: 0 }, // остывание
  ],
  // Пайплайн сломается если порог не достигнут
  thresholds: {
    http_req_duration: [
      'p(95)<500', // p95 < 500мс
      'p(99)<1000', // p99 < 1000мс
    ],
    errors: ['rate<0.01'], // ошибок < 1%
    http_req_failed: ['rate<0.01'], // HTTP ошибок < 1%
    post_create_duration: ['p(95)<800'],
  }
}

const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000'
const AUTH_TOKEN = __ENV.AUTH_TOKEN

export function setup() {
  // Один раз: получить токен или подготовить данные
  const res = http.post(`${BASE_URL}/api/auth/login`, JSON.stringify({
    email: '[email protected]',
    password: 'testpassword'
  }), {
    headers: { 'Content-Type': 'application/json' }
  })
  return { token: res.json('token') }
}

export default function(data) {
  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${data.token || AUTH_TOKEN}`
  }

  // Сценарий 1: список постов (70% трафика)
  const postsList = http.get(`${BASE_URL}/api/posts?limit=20`, { headers })
  check(postsList, {
    'posts list: status 200': (r) => r.status === 200,
    'posts list: has items': (r) => r.json('data').length > 0
  })
  errorRate.add(postsList.status !== 200)
  sleep(Math.random() * 0.5) // случайная пауза 0-500мс

  // Сценарий 2: создание поста (20% трафика)
  if (Math.random() < 0.2) {
    const start = Date.now()
    const createPost = http.post(`${BASE_URL}/api/posts`, JSON.stringify({
      title: `Test post ${Date.now()}`,
      content: 'Load test content'
    }), { headers })
    postCreateDuration.add(Date.now() - start)
    check(createPost, {
      'create post: status 201': (r) => r.status === 201,
    })
    errorRate.add(createPost.status !== 201)
  }

  sleep(0.3)
}

כיצד להגדיר ספי ביצועים ב-k6?

ספים הם המנגנון המרכזי לכשל אוטומטי של הצנרת. באפשרויות הסקריפט, אנו מגדירים גבולות מקובלים: לדוגמה, // tests/performance/api-smoke.js import http from 'k6/http' import { check, sleep } from 'k6' import { Rate, Trend } from 'k6/metrics' // Кастомные метрики const errorRate = new Rate('errors') const postCreateDuration = new Trend('post_create_duration') export const options = { // Профиль нагрузки для CI: быстро, не разрушительно stages: [ { duration: '30s', target: 10 }, // разогрев { duration: '1m', target: 10 }, // устойчивая нагрузка { duration: '10s', target: 0 }, // остывание ], // Пайплайн сломается если порог не достигнут thresholds: { http_req_duration: [ 'p(95)<500', // p95 < 500мс 'p(99)<1000', // p99 < 1000мс ], errors: ['rate<0.01'], // ошибок < 1% http_req_failed: ['rate<0.01'], // HTTP ошибок < 1% post_create_duration: ['p(95)<800'], } } const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000' const AUTH_TOKEN = __ENV.AUTH_TOKEN export function setup() { // Один раз: получить токен или подготовить данные const res = http.post(`${BASE_URL}/api/auth/login`, JSON.stringify({ email: '[email protected]', password: 'testpassword' }), { headers: { 'Content-Type': 'application/json' } }) return { token: res.json('token') } } export default function(data) { const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${data.token || AUTH_TOKEN}` } // Сценарий 1: список постов (70% трафика) const postsList = http.get(`${BASE_URL}/api/posts?limit=20`, { headers }) check(postsList, { 'posts list: status 200': (r) => r.status === 200, 'posts list: has items': (r) => r.json('data').length > 0 }) errorRate.add(postsList.status !== 200) sleep(Math.random() * 0.5) // случайная пауза 0-500мс // Сценарий 2: создание поста (20% трафика) if (Math.random() < 0.2) { const start = Date.now() const createPost = http.post(`${BASE_URL}/api/posts`, JSON.stringify({ title: `Test post ${Date.now()}`, content: 'Load test content' }), { headers }) postCreateDuration.add(Date.now() - start) check(createPost, { 'create post: status 201': (r) => r.status === 201, }) errorRate.add(createPost.status !== 201) } sleep(0.3) } . זה אומר ש-95% מהבקשות חייבות להיות מהירות מ-500ms, ו-99% מהירות משנייה אחת. אם סף מופר, הבדיקה מסתיימת עם שגיאה, ו-CI עוצר את הפריסה.

אנו משתמשים גם במדדים מותאמים אישית עבור פעולות עסקיות ספציפיות (למשל, זמן יצירת פוסט) ומגדירים ספים נפרדים עליהם. כך, אתה יודע בוודאות שפונקציונליות קריטית אינה מתדרדרת.

אינטגרציה עם GitHub Actions

---
# .github/workflows/performance.yml
name: Performance Tests
on:
  push:
    branches: [main, staging]
  pull_request:
    branches: [main]
jobs:
  performance:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_DB: testdb
          POSTGRES_PASSWORD: testpass
        ports: ['5432:5432']
        options: >-
          --health-cmd pg_isready --health-interval 10s
    steps:
      - uses: actions/checkout@v4
      - name: Start application
        run: |
          docker compose -f docker-compose.test.yml up -d api
          npx wait-on http://localhost:3000/health --timeout 60000
      - name: Run k6 smoke test
        uses: grafana/[email protected]
        with:
          filename: tests/performance/api-smoke.js
          flags: --out json=results.json
        env:
          BASE_URL: http://localhost:3000
          K6_PROMETHEUS_RW_SERVER_URL: ${{ secrets.PROMETHEUS_URL }}
      - name: Parse results
        if: always()
        run: |
          # Показать summary в PR комментарии
          jq -r '.metrics | { p95: .http_req_duration["p(95)"], p99: .http_req_duration["p(99)"], errors: .http_req_failed.rate }' results.json
      - name: Comment PR with results
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs')
            const results = JSON.parse(fs.readFileSync('results.json'))
            const p95 = results.metrics.http_req_duration['p(95)'].toFixed(0)
            const errorRate = (results.metrics.http_req_failed.rate * 100).toFixed(2)
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## Performance Test Results\n\n| Metric | Value | Threshold |\n|--------|-------|-----------|\n| p95 latency | ${p95}ms | <500ms |\n| Error rate | ${errorRate}% | <1% |`
            })
---

השוואת בסיס בין פריסות

#!/bin/bash
# scripts/compare-performance.sh
CURRENT_BRANCH=$(git branch --show-current)
BASELINE_BRANCH="main"

# Тест текущего кода
k6 run --out json=current.json tests/performance/api-smoke.js

# Переключиться на baseline
git stash
git checkout $BASELINE_BRANCH
docker compose up -d --build api
sleep 10
k6 run --out json=baseline.json tests/performance/api-smoke.js

# Сравнение
node - <<'EOF'
const current = require('./current.json')
const baseline = require('./baseline.json')
const metrics = ['http_req_duration']
for (const m of metrics) {
  const cp95 = current.metrics[m]['p(95)']
  const bp95 = baseline.metrics[m]['p(95)']
  const delta = ((cp95 - bp95) / bp95 * 100).toFixed(1)
  if (cp95 > bp95 * 1.2) {
    // регрессия > 20%
    console.error(`REGRESSION: ${m} p95 degraded by ${delta}%`)
    process.exit(1)
  }
  console.log(`${m} p95: ${cp95}ms vs ${bp95}ms baseline (${delta}%)`)
}
EOF

# Вернуться на текущую ветку
git checkout $CURRENT_BRANCH
git stash pop

Artillery לתיאור תרחישים

---
# tests/performance/user-journey.yml
config:
  target: "{{ $processEnvironment.BASE_URL }}"
  phases:
    - duration: 60
      arrivalRate: 5
      rampTo: 20
      name: "Ramp up"
    - duration: 120
      arrivalRate: 20
      name: "Sustained load"
  ensure:
    thresholds:
      - http.response_time.p95: 500
      - http.request_rate: 15
scenarios:
  - name: "Browse and purchase"
    weight: 70
    flow:
      - get:
          url: "/api/products"
          expect:
            - statusCode: 200
      - post:
          url: "/api/cart"
          json:
            productId: "{{ $randomInt(1, 100) }}"
            quantity: 1
  - name: "Search only"
    weight: 30
    flow:
      - get:
          url: "/api/search?q={{ $randomString(5) }}"

השוואת כלי בדיקת עומס

תכונה k6 Artillery Gatling
שפת סקריפטים JavaScript YAML Scala/Java
אינטגרציית CI טבעית כן (GitHub Actions, GitLab CI) כן (דרך NPM) כן (Maven/Gradle)
ספים מובנים כן כן (דרך ensure) כן
יצירת דוחות JSON, Prometheus, HTML JSON, HTML HTML (מפורט)
ביצועים גבוהים (Go) בינוניים (Node.js) גבוהים (JVM)
רישיון קוד פתוח (AGPL) קוד פתוח (MPL) קוד פתוח (ALv2)

למה להשתמש ב-k6 עבור CI?

ל-k6 יש תמיכה מובנית ב-CI/CD: הוא פועל ככלי CLI, אינו דורש GUI, וניתן להוציא תוצאות ל-JSON לעיבוד נוסף. בניגוד ל-Gatling (דורש Scala/Java ויצירת דוחות HTML) או Artillery (תצורות YAML, אבל פחות מדדים), k6 מספק מדדים גמישים ואינטגרציה פשוטה עם GitHub Actions דרך פעולות מוכנות. עבור צוותים שכבר משתמשים ב-JavaScript, סף הכניסה מינימלי.

תהליך העבודה

  1. ניתוח — זיהוי נקודות קצה קריטיות ותרחישי משתמש.
  2. עיצוב — פיתוח תרחישי עומס, הגדרת פרופילי עומס (ramp-up, מתמשך).
  3. יישום — כתיבת סקריפטים (k6, Artillery, או Gatling), אינטגרציה ל-CI.
  4. בדיקה — הרצת בדיקות עשן על staging, כוונון ספים.
  5. פריסה — הכללת בדיקות בצנרת, הגדרת תגובות PR אוטומטיות.

לוחות זמנים ומה כלול

הגדרת סט בסיסי של בדיקות עשן k6 עם ספים ואינטגרציית CI אורכת בין יום ל-2 ימי עסקים. אם נדרשת השוואת בסיס ומדדים מותאמים אישית, אנו מאריכים ל-3-5 ימים. ההיקף כולל:

  • סקריפטים לבדיקת עומס (2-3 תרחישים)
  • הגדרת ספים
  • אינטגרציה עם GitHub Actions או GitLab CI (צנרת YAML)
  • תגובת PR עם תוצאות בדיקה
  • תיעוד להרצה ותחזוקה
  • ייעוץ לצוות בנושא פרשנות תוצאות

אנו מבטיחים שהבדיקות לא יפריעו לתהליך הפיתוח הראשי: הן רצות במקביל ואורכות לא יותר מ-5 דקות.

למה לבחור בנו

  • ניסיון של למעלה מ-5 שנים בבדיקות עומס ו-CI/CD
  • 50+ פרויקטים מוצלחים — מסטארטאפים ועד ארגונים
  • אנו משתמשים רק בכלים מוכחים (k6, Grafana, Prometheus)
  • אנו מספקים אחריות על פעולת בדיקות תקינה למשך חודש לאחר היישום

צור קשר כדי לדון בפרויקט שלך: קבל ייעוץ על שילוב בדיקות עומס רציפות בצנרת שלך.