Performance & Scalability serimizin bir parçası
Tam kılavuzu okuyunBir ürünü yük testi olmadan göndermek bir kumardır. Kırılma noktanızı, kullanıcılar sizin için bulana kadar bilemezsiniz; genellikle ürün lansmanı, viral bir an veya satış artışı sırasında. k6, JavaScript'te testler yazmanıza, bunları CI'dan çalıştırmanıza ve performans tavanınızı kullanıcılardan önce keşfetmenize olanak tanıyan modern yük testi aracıdır. Geliştirici dostudur, kaynak açısından verimlidir (k6 iş parçacıklarını değil goroutinleri kullanır) ve gerçek zamanlı ölçümler için Grafana ve Prometheus ile temiz bir şekilde bütünleşir.
Bu kılavuz, ilk komut dosyasından başlayarak karmaşık çok senaryolu yük testlerine, özel ölçümlere, eşiklere, CI entegrasyonuna ve Node.js/NestJS API'leri için üretim açısından güvenli test modellerine kadar k6'yı kapsar.
Önemli Çıkarımlar
- k6 komut dosyaları JavaScript'tir ancak Go çalışma zamanında çalışır — Node.js API'leri yoktur (
requireyok,fsyok,setTimeoutyok)- Sanal Kullanıcılar (VU'lar) eşzamanlı simüle edilmiş kullanıcılardır; yinelemeler bireysel komut dosyası yürütmeleridir
- Çalıştırmadan önce daima eşikleri ayarlayın — başarısız olan eşikler testi durdurur ve CI'da başarısız olur
- Gerçek trafik modellerini modellemek için senaryoları (sabit-vus, artan-vus, sabit-varış oranı) kullanın
- Operasyonlarla koordine olmadan test üretimini asla yüklemeyin; aşamalandırmaya veya üretim klonuna karşı test yapın
http_req_durationmetriği birincil SLA metriğinizdir — p95 ve p99 ortalamalardan daha önemlidir- k6 koşucularınıza hız sınırlaması — yük testi trafiği, hız sınırı bütçenizi tüketmemelidir
- Coğrafi bölgeler arasında dağıtılmış yük testi için k6 Cloud veya Grafana k6'yı kullanın
Kurulum ve İlk Komut Dosyası
# macOS
brew install k6
# Ubuntu/Debian
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
# Windows (via Chocolatey)
choco install k6
İlk k6 betiğiniz:
// k6/homepage-load.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate } from 'k6/metrics';
// Custom metric: error rate
const errorRate = new Rate('error_rate');
export const options = {
// Ramp up to 50 VUs over 1 minute, hold 2 minutes, ramp down
stages: [
{ duration: '1m', target: 50 },
{ duration: '2m', target: 50 },
{ duration: '1m', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<500', 'p(99)<1000'], // 95th pct < 500ms
http_req_failed: ['rate<0.01'], // Less than 1% errors
error_rate: ['rate<0.01'],
},
};
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';
export default function () {
const res = http.get(`${BASE_URL}/`);
const ok = check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
'body contains ECOSIRE': (r) => r.body.includes('ECOSIRE'),
});
errorRate.add(!ok);
sleep(1); // 1 second think time between iterations
}
Çalıştır:
k6 run k6/homepage-load.js
k6 run --env BASE_URL=https://staging.ecosire.com k6/homepage-load.js
k6 run --vus 100 --duration 30s k6/homepage-load.js # Quick smoke test
Kimlik Doğrulamayla API Yük Testi
// k6/api-load.js
import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { Counter, Trend } from 'k6/metrics';
const apiCalls = new Counter('api_calls');
const authDuration = new Trend('auth_duration');
export const options = {
scenarios: {
// Constant arrival rate: 100 requests/second regardless of VU count
constant_load: {
executor: 'constant-arrival-rate',
rate: 100,
timeUnit: '1s',
duration: '3m',
preAllocatedVUs: 50,
maxVUs: 200,
},
},
thresholds: {
http_req_duration: ['p(95)<300', 'p(99)<500'],
'http_req_duration{type:api}': ['p(95)<200'],
http_req_failed: ['rate<0.005'], // 0.5% error budget
},
};
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3001';
// setup() runs once before VUs start
export function setup() {
// Authenticate and return tokens for VUs to use
const loginRes = http.post(`${BASE_URL}/auth/login`, JSON.stringify({
email: __ENV.TEST_EMAIL,
password: __ENV.TEST_PASSWORD,
}), {
headers: { 'Content-Type': 'application/json' },
});
check(loginRes, { 'login successful': (r) => r.status === 200 });
const { accessToken } = loginRes.json();
return { accessToken };
}
export default function (data) {
const { accessToken } = data;
const headers = {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
};
group('Contacts API', () => {
// List contacts
const listRes = http.get(`${BASE_URL}/contacts?page=1&limit=20`, {
headers,
tags: { type: 'api', endpoint: 'contacts-list' },
});
check(listRes, {
'list contacts: 200': (r) => r.status === 200,
'list contacts: has items': (r) => r.json('data') !== null,
});
apiCalls.add(1);
sleep(0.5);
// Create a contact
const createRes = http.post(`${BASE_URL}/contacts`, JSON.stringify({
name: `Load Test User ${Date.now()}`,
email: `load-test-${Date.now()}@example.com`,
}), {
headers,
tags: { type: 'api', endpoint: 'contacts-create' },
});
check(createRes, {
'create contact: 201': (r) => r.status === 201,
});
apiCalls.add(1);
});
sleep(1);
}
// teardown() runs once after all VUs finish
export function teardown(data) {
// Clean up test data if needed
console.log(`Test complete. Data: ${JSON.stringify(data)}`);
}
Artan Değer Birimi Senaryoları
Birden fazla aşama ve senaryoyla gerçek trafik modellerini modelleyin:
// k6/stress-test.js
export const options = {
scenarios: {
// Scenario 1: Normal traffic baseline
normal_traffic: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 20 },
{ duration: '5m', target: 20 },
],
gracefulRampDown: '30s',
},
// Scenario 2: Sudden spike (marketing campaign goes live)
traffic_spike: {
executor: 'ramping-vus',
startVUs: 0,
startTime: '7m', // Starts after baseline is stable
stages: [
{ duration: '30s', target: 200 }, // Rapid spike
{ duration: '2m', target: 200 }, // Hold spike
{ duration: '30s', target: 20 }, // Fall back
],
},
// Scenario 3: Soak test for memory leaks
soak_test: {
executor: 'constant-vus',
vus: 10,
duration: '30m', // Run for 30 minutes
startTime: '10m',
},
},
thresholds: {
'http_req_duration{scenario:normal_traffic}': ['p(95)<300'],
'http_req_duration{scenario:traffic_spike}': ['p(95)<800'],
http_req_failed: ['rate<0.02'],
},
};
Blog/Site Haritası Tarama Testi
// k6/sitemap-crawl.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { SharedArray } from 'k6/data';
// Load URLs from sitemap (pre-fetched and saved as JSON)
const urls = new SharedArray('sitemap urls', function () {
// In real usage, fetch sitemap XML and parse URLs beforehand
// SharedArray is loaded once and shared across all VUs (memory efficient)
return JSON.parse(open('./sitemap-urls.json'));
});
export const options = {
vus: 20,
duration: '5m',
thresholds: {
http_req_duration: ['p(95)<2000'], // Public pages can be slower
http_req_failed: ['rate<0.01'],
},
};
export default function () {
// Each VU picks a random URL from the sitemap
const url = urls[Math.floor(Math.random() * urls.length)];
const res = http.get(url, {
headers: {
// Identify as load tester in logs
'User-Agent': 'k6-load-tester/1.0',
},
timeout: '10s',
});
check(res, {
'status is 200': (r) => r.status === 200,
'no error page': (r) => !r.body.includes('Error'),
'has canonical tag': (r) => r.body.includes('rel="canonical"'),
'response time < 2000ms': (r) => r.timings.duration < 2000,
});
sleep(Math.random() * 2 + 1); // Random 1-3 second think time
}
Özel Metrikler ve Eşikler
// k6/checkout-load.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Counter, Rate, Trend, Gauge } from 'k6/metrics';
// Custom metrics for business-specific tracking
const checkoutSuccesses = new Counter('checkout_successes');
const checkoutFailures = new Counter('checkout_failures');
const checkoutDuration = new Trend('checkout_duration');
const activeCheckouts = new Gauge('active_checkouts');
export const options = {
stages: [
{ duration: '1m', target: 10 },
{ duration: '3m', target: 30 },
{ duration: '1m', target: 0 },
],
thresholds: {
checkout_duration: ['p(95)<3000'], // Checkout < 3s at p95
checkout_failures: ['count<10'], // Max 10 absolute failures
http_req_duration: ['p(99)<2000'],
},
};
export default function (data) {
activeCheckouts.add(1);
const start = Date.now();
// Step 1: Add to cart
const cartRes = http.post('/api/cart/add', JSON.stringify({
productId: 'prod_odoo_customization',
quantity: 1,
}), { headers: { 'Content-Type': 'application/json' } });
if (!check(cartRes, { 'add to cart: 200': (r) => r.status === 200 })) {
checkoutFailures.add(1);
activeCheckouts.add(-1);
return;
}
sleep(2);
// Step 2: Create checkout session
const checkoutRes = http.post('/api/billing/checkout', JSON.stringify({
cartId: cartRes.json('cartId'),
}), { headers: { 'Content-Type': 'application/json' } });
const success = check(checkoutRes, {
'checkout session created': (r) => r.status === 200,
'has session URL': (r) => r.json('url') !== null,
});
if (success) {
checkoutSuccesses.add(1);
checkoutDuration.add(Date.now() - start);
} else {
checkoutFailures.add(1);
}
activeCheckouts.add(-1);
sleep(1);
}
Grafana Çıkış Entegrasyonu
K6 ölçümlerini InfluxDB'ye aktarın ve test sırasında Grafana'da görselleştirin:
# Run with InfluxDB output
k6 run --out influxdb=http://localhost:8086/k6 k6/api-load.js
# Or use the k6 Grafana integration (k6 v0.45+)
k6 run --out experimental-prometheus-rw k6/api-load.js
# docker-compose.monitoring.yml
services:
influxdb:
image: influxdb:2.7
ports: ["8086:8086"]
environment:
INFLUXDB_DB: k6
INFLUXDB_ADMIN_USER: admin
INFLUXDB_ADMIN_PASSWORD: password
grafana:
image: grafana/grafana:latest
ports: ["3030:3000"]
environment:
GF_AUTH_ANONYMOUS_ENABLED: "true"
volumes:
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards
- ./grafana/datasources:/etc/grafana/provisioning/datasources
CI Entegrasyonu
# .github/workflows/ci.yml (load test section)
load-tests:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # Only on main branch
needs: [deploy-staging]
steps:
- uses: actions/checkout@v4
- name: Install k6
run: |
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
- name: Run smoke test (30 VUs, 60s)
run: |
k6 run --vus 30 --duration 60s \
--env BASE_URL=${{ secrets.STAGING_URL }} \
--env TEST_EMAIL=${{ secrets.TEST_EMAIL }} \
--env TEST_PASSWORD=${{ secrets.TEST_PASSWORD }} \
apps/api/k6/api-load.js
- name: Upload k6 results
uses: actions/upload-artifact@v4
if: always()
with:
name: k6-results
path: k6-results/
Performans Temelleri
Temelleri belirleyin ve gerilemeler konusunda uyarıda bulunun:
| Uç nokta | p50 | s95 | s99 | Hata Bütçesi |
|---|---|---|---|---|
GET / (ana sayfa) | 120ms | 400ms | 800ms | %0,1 |
| KOD0 | 50ms | 150ms | 300ms | %0,5 |
| KOD0 | 80ms | 200ms | 400ms | %0,5 |
| KOD0 | 200ms | 500ms | 1000ms | %1 |
| KOD0 | 500ms | 1500ms | 3000ms | %1 |
| KOD0 | 100ms | 300ms | 600ms | %0,1 |
Sıkça Sorulan Sorular
VU'lar ile saniye başına istekler arasındaki fark nedir?
VU'lar (Sanal Kullanıcılar) eşzamanlı simüle edilmiş kullanıcılardır. Her VU, varsayılan işlevinizi bir döngüde çalıştırır. Saniyedeki istekler her yinelemenin ne kadar hızlı çalıştığına bağlıdır. Her VU yinelemesi 2 saniye sürerse (uyku süresi dahil) ve 100 VU'nuz varsa, yaklaşık 50 RPS elde edersiniz. Yineleme süresine bakılmaksızın belirli bir RPS'yi hedeflemeniz gerektiğinde constant-arrival-rate yürütücüsünü kullanın.
Testi üretime mi yoksa aşamalandırmaya mı göre yüklemeliyim?
Her zaman sahnelemeyi tercih edin. Üretim yükü testleri, gerçek kullanıcıları etkileme, hız sınırlarını tüketme, test verilerinden gerçek siparişler oluşturma ve gerçek webhook olaylarını tetikleme riskini taşır. Üretimi test etmeniz gerekiyorsa bunu trafiğin düşük olduğu dönemlerde yapın, ödeme jetonlarını test edin ve bir geri alma planınız olsun. k6 Cloud, coğrafi olarak dağıtılmış yük oluşturmayı destekler, böylece CDN uç performansınızı kaynağa dokunmadan test edebilirsiniz.
Uzun testler sırasında kimlik doğrulama jetonunun süresinin dolmasıyla nasıl başa çıkabilirim?
Kısa testler için (15 dakikanın altında), setup() şeklinde bir jeton alın ve bunu data aracılığıyla tüm Değer Birimi'ne iletin. Uzun testler için (15 dakikanın üzerinde), test komut dosyasında belirteç yenilemeyi uygulayın: varsayılan işlevdeki belirteç yaşını kontrol edin ve sürenin dolmasına yaklaştığında yenileyin. Belirteci her bir Değer Birimi için yerel olan bir JavaScript değişkeninde saklayın.
stages ile scenarios arasındaki fark nedir?
stages, tek bir ramping-vus senaryosunun kısa yoludur; basit artış/tutma/azalış modelleri için iyidir. scenarios size tam kontrol sağlar: birden fazla eşzamanlı trafik modeli, senaryo başına farklı uygulayıcılar, senaryo başına eşikler ve metriklerde senaryo etiketleme. Gerçekçi çoklu model testleri için scenarios kullanın (aynı anda taban çizgisi + artış + ıslatma).
Tek bir k6 işlemi kaç adet VU'yu işleyebilir?
Modern donanımdaki tek bir k6 işlemi, komut dosyası karmaşıklığına ve yanıt boyutuna bağlı olarak 5.000-10.000 VU'yu sürdürebilir ve 50.000-100.000 RPS üretebilir. Daha yüksek yükler için k6 cloud kullanın veya bir yük dağıtıcısının arkasında birden çok k6 örneğini çalıştırın. Her VU son derece hafiftir (bir goroutine) — k6, eşdeğer VU sayıları için JMeter veya Gatling'den çok daha az kaynak kullanır.
Sonraki Adımlar
Yük testi, kullanıcılar uygulamanızı stres altında keşfetmeden önce uygulamanızın gerçek performans profilini ortaya çıkarır. Bu kılavuzdaki modeller (yükseltme senaryoları, özel eşikler, CI entegrasyonu ve Grafana kontrol panelleri) size performans darboğazlarını sürekli olarak bulmanız ve düzeltmeniz için gereken altyapıyı sağlar.
ECOSIRE, ana sayfayı, API uç noktalarını, ödeme akışlarını ve tam site haritası taramalarını kapsayan k6 yük testleriyle performansı doğrulanmış NestJS API'leri oluşturur. İlk günden itibaren performansa yönelik nasıl geliştirmeler yaptığımızı öğrenmek için arka uç mühendislik hizmetlerimizi keşfedin.
Yazan
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
ECOSIRE
ECOSIRE ile İşinizi Büyütün
ERP, e-Ticaret, yapay zeka, analitik ve otomasyon genelinde kurumsal çözümler.
İlgili Makaleler
Shopify Hız Optimizasyonu: Temel Web Verilerini Gerçekten Yönlendiren Teknik Bir Kontrol Listesi (2026)
2026 için sahada test edilmiş Shopify hız kontrol listesi - gerçek mağazalarda LCP, INP ve CLS'yi gerçekte neyin iyileştirdiği, neyin zaman kaybettirdiği ve uygulamaların ve temaların nasıl denetleneceği.
Odoo 19 HR: Beceri Matrisi, Kariyer Planları, Performans Döngüleri
Odoo 19 İK yükseltmesi: yerel beceriler matrisi, kariyer yolu planlaması, performans inceleme döngüleri, 9 kutulu tablo, yedekleme planlaması, HRIS entegrasyonu.
Odoo 19 Performans Karşılaştırmaları: PostgreSQL 17 Ayar Numaraları
Gerçek dünya Odoo 19 performans kıyaslamaları: web istemci hızı, ORM verimi, PG17 ayarlama ayarları, bağlantı havuzu oluşturma, çalışan sayıları, ölçeklendirme eşikleri.
Performance & Scalability serisinden daha fazlası
Shopify Hız Optimizasyonu: Temel Web Verilerini Gerçekten Yönlendiren Teknik Bir Kontrol Listesi (2026)
2026 için sahada test edilmiş Shopify hız kontrol listesi - gerçek mağazalarda LCP, INP ve CLS'yi gerçekte neyin iyileştirdiği, neyin zaman kaybettirdiği ve uygulamaların ve temaların nasıl denetleneceği.
Teknik SEO Denetim Kontrol Listesi 2026: Her Müşteri Sitesinde Çalıştırdığımız 47 Kontrol
2026'da her müşteri sitesinde yürüttüğümüz 47 maddelik teknik SEO denetim kontrol listesi: taranabilirlik, dizine ekleme, kanonik bilgiler, hreflang, Önemli Web Verileri ve günlükler.
Odoo 19 HR: Beceri Matrisi, Kariyer Planları, Performans Döngüleri
Odoo 19 İK yükseltmesi: yerel beceriler matrisi, kariyer yolu planlaması, performans inceleme döngüleri, 9 kutulu tablo, yedekleme planlaması, HRIS entegrasyonu.
Odoo 19 Performans Karşılaştırmaları: PostgreSQL 17 Ayar Numaraları
Gerçek dünya Odoo 19 performans kıyaslamaları: web istemci hızı, ORM verimi, PG17 ayarlama ayarları, bağlantı havuzu oluşturma, çalışan sayıları, ölçeklendirme eşikleri.
OpenClaw Maliyet Optimizasyonu ve Büyük Ölçekte Token Verimliliği
OpenClaw belirteci maliyet optimizasyonu: hızlı önbelleğe alma, model yönlendirme, yanıt önbelleğe alma, toplu API'ler ve üretim aracıları için kiracı başına maliyet korkulukları.
10 Milyon Satırdan Fazla Tablolar için Power BI Artımlı Yenileme
10 milyondan fazla satır tablosu için Power BI Artımlı Yenileme oyun kitabı: bölüm tasarımı, RangeStart/RangeEnd, yenileme ilkeleri, sorgu katlama ve DirectQuery hibritleri.