Симуляція реального трафіку: k6, логи, сценарії

Відтворення реального трафіку: від логів до k6-сценаріїв

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Симуляція реального трафіку: k6, логи, сценарії
Середній
~2-3 дні

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1418
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    983
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1243
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    997

Відтворення реального трафіку: від логів до k6-сценаріїв

При навантажувальному тестуванні типова помилка — використовувати рівномірну подачу запитів з фіксованим числом віртуальних користувачів. У реальності трафік має піки (вранці та ввечері), різні типи користувачів (мобільні браузери, API-клієнти), випадкові паузи та розподіл 80/20. Наприклад, 80% запитів припадають на 20% сторінок. Синтетичні тести часто пропускають проблеми з кешуванням, сесійним станом та конкурентністю.

Ми пропонуємо підхід, заснований на аналізі реального трафіку з логів Nginx або Google Analytics, і генерації сценаріїв для k6, які точно відтворюють поведінку справжніх користувачів. Реалістичне тестування виявляє в три рази більше вузьких місць, ніж рівномірне. Замовники економлять у середньому 40 000–80 000 грн на налагодженні завдяки ранньому виявленню проблем. Зв'яжіться з нами для обговорення вашого проєкту.

Як працює аналіз логів?

# Вилучити паттерни з nginx access log import re from collections import Counter, defaultdict import json def analyze_access_log(log_file: str): pattern = re.compile( r'(?P<ip>\S+) .+ \[(?P<time>[^\]]+)\] ' r'"(?P<method>\w+) (?P<path>[^"]+) HTTP/\d+" ' r'(?P<status>\d+) (?P<bytes>\d+)' ) endpoint_counts = Counter() method_counts = Counter() hourly_traffic = defaultdict(int) with open(log_file) as f: for line in f: m = pattern.match(line) if not m: continue # Нормалізувати path (прибрати ID) path = re.sub(r'/\d+', '/{id}', m.group('path').split('?')[0]) endpoint_counts[f"{m.group('method')} {path}"] += 1 method_counts[m.group('method')] += 1 # Погодинний розподіл hour = m.group('time').split(':')[1] hourly_traffic[hour] += 1 total = sum(endpoint_counts.values()) print("=== Top Endpoints (% of traffic) ===") for endpoint, count in endpoint_counts.most_common(20): pct = count / total * 100 print(f" {pct:.1f}% {endpoint}") print("\n=== Hourly Distribution ===") for hour in sorted(hourly_traffic): bar = '█' * (hourly_traffic[hour] // 100) print(f" {hour}:00 {bar} {hourly_traffic[hour]}") # Експорт для k6 сценарію weights = {ep: round(cnt/total, 3) for ep, cnt in endpoint_counts.most_common(20)} return weights 

Отримані ваги експортуються в JSON і використовуються для генерації сценаріїв k6. Аналіз access-логів дозволяє виділити 20% ендпоінтів, що генерують 80% трафіку, згідно із законом Парето.

Обмеження рівномірного трафіку

Рівномірне навантаження не створює ефекту "натовпу": коли 1000 користувачів одночасно переходять на один товар після публікації в соцмережах. Воно не перевіряє сесійне кешування, блокування БД при конкурентному записі або деградацію під постійними піками. Реалістична симуляція з розподілом Pareto (80/20) та сесійною поведінкою відтворює такі сценарії, виявляючи вузькі місця до деплою в прод.

Як побудувати сценарій на основі логів?

На основі вилучених ваг ми генеруємо сценарії k6. Для кожного типу користувача створюється окремий executor з різною інтенсивністю. Наприклад, 40% трафіку — анонімні браузери, 50% — авторизовані користувачі, 10% — API-клієнти. Сценарії включають випадкові паузи, розгалуження та ймовірнісні переходи.

// tests/realistic/user-journey.js import http from 'k6/http' import { check, sleep } from 'k6' import { SharedArray } from 'k6/data' import { randomItem, randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js' // Завантажити тестові дані з CSV const users = new SharedArray('users', function() { return open('./data/test-users.csv').split('\n') .slice(1) .map(row => { const [email, token, userId] = row.split(',') return { email, token, userId } }) }) const searchTerms = new SharedArray('searches', function() { return open('./data/popular-searches.txt').split('\n').filter(Boolean) }) export const options = { scenarios: { // Анонімні браузери (40% трафіку) anonymous_browse: { executor: 'ramping-vus', startVUs: 0, stages: [ { duration: '5m', target: 40 }, { duration: '30m', target: 40 }, { duration: '5m', target: 0 } ], exec: 'anonymousBrowse' }, // Авторизовані користувачі (50% трафіку) logged_in_users: { executor: 'ramping-vus', startVUs: 0, stages: [ { duration: '5m', target: 50 }, { duration: '30m', target: 50 }, { duration: '5m', target: 0 } ], exec: 'loggedInJourney' }, // API-клієнти (10% трафіку) api_clients: { executor: 'constant-arrival-rate', rate: 10, timeUnit: '1s', duration: '40m', preAllocatedVUs: 20, exec: 'apiClient' } }, thresholds: { http_req_duration: ['p(95)<800'], http_req_failed: ['rate<0.01'], } } const BASE = __ENV.BASE_URL || 'https://staging.example.com' // Сценарій: анонімний браузер export function anonymousBrowse() { // Лендінг → каталог → товар → вихід http.get(`${BASE}/`) sleep(randomIntBetween(1, 4)) const category = randomItem(['electronics', 'clothing', 'books', 'sports']) http.get(`${BASE}/api/products?category=${category}&limit=20`) sleep(randomIntBetween(2, 8)) // 30% ідуть одразу, 70% дивляться товар if (Math.random() > 0.3) { const productId = randomIntBetween(1, 500) http.get(`${BASE}/api/products/${productId}`) sleep(randomIntBetween(3, 15)) } // 20% роблять пошук if (Math.random() < 0.2) { const term = randomItem(searchTerms) http.get(`${BASE}/api/search?q=${encodeURIComponent(term)}`) sleep(randomIntBetween(1, 5)) } } // Сценарій: авторизований користувач export function loggedInJourney() { const user = randomItem(users) const headers = { 'Authorization': `Bearer ${user.token}`, 'Content-Type': 'application/json' } // Профіль http.get(`${BASE}/api/me`, { headers }) sleep(randomIntBetween(1, 3)) // Перегляд товарів for (let i = 0; i < randomIntBetween(2, 8); i++) { const productId = randomIntBetween(1, 500) http.get(`${BASE}/api/products/${productId}`, { headers }) sleep(randomIntBetween(2, 10)) } // 40% додають в кошик if (Math.random() < 0.4) { http.post(`${BASE}/api/cart/items`, JSON.stringify({ productId: randomIntBetween(1, 500), quantity: randomIntBetween(1, 3) }), { headers }) sleep(randomIntBetween(1, 3)) // 60% з тих, хто додав — оформлюють замовлення if (Math.random() < 0.6) { http.get(`${BASE}/api/cart`, { headers }) sleep(randomIntBetween(2, 5)) const checkout = http.post(`${BASE}/api/orders`, JSON.stringify({ paymentMethod: 'saved_card', shippingAddressId: 1 }), { headers }) check(checkout, { 'order created': (r) => r.status === 201 }) } } } // Сценарій: API-клієнт (інтеграція) export function apiClient() { const apiKey = __ENV.API_KEY const headers = { 'X-API-Key': apiKey, 'Content-Type': 'application/json' } // Синхронізація продуктів const r = http.get(`${BASE}/api/v1/products?since=${Date.now() - 3600000}`, { headers }) check(r, { 'api: 200': (r) => r.status === 200 }) } 

Реалістичний сценарій дає в 1,5 рази точніше моделювання порівняно з рівномірним.

Розподіл Pareto в k6

Реальний трафік: 20% сторінок отримують 80% трафіку. В k6 це моделюється функцією, що генерує ID за степеневим законом:

// Генератор Pareto-розподілу для ID function paretoId(maxId, shape = 1.5) { const u = Math.random() return Math.ceil(maxId * Math.pow(1 - u, 1 / shape)) } // Використання const productId = paretoId(10000) // переважно ID 1-200, рідко ID 9000+ 

Порівняння синтетичного та реалістичного тестування

Характеристика Синтетичне тестування Реалістичне тестування
Тип трафіку Рівномірний, заданий вручну Відтворює реальні паттерни (піки, сесії)
Поведінка користувачів Однакові сценарії для всіх VU Різні сценарії (аноніми, авторизовані, API)
Шлях користувача Лінійний (головна → товар → кошик) Розгалужений з ймовірнісними переходами
Виявлення вузьких місць Тільки пропускна здатність Кешування, повільні ендпоінти, конкурентність
Час підготовки Години Дні (потрібен аналіз логів)

Процес роботи

  1. Аналіз логів: збір access-логів Nginx або даних Google Analytics, вилучення паттернів (ендпоінти, статуси, погодинний розподіл).
  2. Проєктування сценаріїв: визначення типів користувачів (анонімні, авторизовані, API), побудова ймовірнісних моделей поведінки.
  3. Реалізація на k6: написання JavaScript-сценаріїв з executors, випадковими паузами та розгалуженнями.
  4. Тестовий прогін: запуск тесту на staging-оточенні, збір метрик (LCP, CLS, TTFB, помилки).
  5. Аналіз та звіт: виявлення вузьких місць, порівняння з baseline, рекомендації з оптимізації.
Етап Тривалість Результат
Аналіз логів 0.5–1 день JSON-профіль ендпоінтів та розподілів
Проєктування сценаріїв 0.5–1 день Ймовірнісні моделі для кожного типу користувача
Реалізація на k6 1–2 дні Робочі k6-скрипти з executors
Тестовий прогін 1 день Метрики, графіки, порогові значення
Звіт та рекомендації 0.5 дня Документ з аналізом та планом оптимізації
Приклад профілю навантаження по годинахТрафік розподілений нерівномірно: пік о 10-11 ранку та 18-19 вечора. В інший час — спад. Ми задаємо ваги для кожної години та генеруємо stages для k6, щоб навантаження відповідало реальному денному циклу.

Результати та терміни

  • Документація сценарію з описом поведінки кожного типу користувачів.
  • Конфігурації k6 (options, thresholds, порогові значення).
  • Звіт з результатами тестування: графіки навантаження, процентилі часу відповіді, помилки.
  • Рекомендації з оптимізації продуктивності (індекси БД, кешування, асинхронні черги).
  • Підтримка при першому запуску та інтерпретації результатів. Ми гарантуємо, що всі сценарії перевірені на наших тестових стендах.

Середня економія на налагодженні — 40 000–80 000 грн завдяки ранньому виявленню вузьких місць. Вартість розробки сценарію — від 30 000 до 50 000 грн.

Розробка реалістичного сценарію навантажувального тесту на основі аналізу реального трафіку займає від 2 до 5 робочих днів. Вартість розраховується індивідуально після ознайомлення з вашими даними.

Замовте реалістичний сценарій навантажувального тестування під ключ. Отримайте консультацію інженерів.