Skip to main content

Eşik Değerleri ve Konfigürasyon

Özet

Ingest Servis'in karar vermesi gereken eşikler (duplicate repeat counters, rate limits, interval thresholds, timeout değerleri vb.) hardcoded değerler değildir. Bunlar deployment-specific ortam değişkenlerinden (environment variables) okunmalı, farklı ortamlar (dev, staging, prod) için farklı threshold'lar kullanılabilmelidir.

Bu sayfa:

  • Environment variable tanımını
  • Ortam-spesifik profilleri
  • Configuration loading pattern'ini
  • Validation rules'i
  • Değerlendirme kılavuzuna

açıklar.

Önerilen Environment Variables

9 temel konfigürasyon değişkeni aşağıdadır:

VariableDefaultAçıklama
INGEST_DUPLICATE_REPEAT_SUSPICIOUS_THRESHOLD3Duplicate tekrar sayısı (suspicious olarak işaretlenene kadar)
INGEST_DUPLICATE_REPEAT_STUCK_THRESHOLD10Duplicate tekrar sayısı (stuck olarak işaretlenene kadar)
INGEST_RATE_SUSPICIOUS_PER_MINUTE12Dakikada paket sayısı (warning flag set)
INGEST_RATE_FLOOD_PER_MINUTE30Dakikada paket sayısı (flood event üretilir)
INGEST_INTERVAL_SUSPICIOUS_DIVISOR4Beklenen aralığın böleni (suspicious: interval < expected/4)
INGEST_INTERVAL_FLOOD_DIVISOR10Beklenen aralığın böleni (flood: interval < expected/10)
INGEST_MAX_PAYLOAD_SIZE_BYTES16384Maksimum HTTP payload boyutu (edge limiteri)
INGEST_REQUEST_TIMEOUT_MS5000İstek timeout süresi (milisaniye)
INGEST_REDIS_DEVICE_BUFFER_TTL_SECONDS86400Redis device_buffer TTL (default: 24 saat)

Environment Profilleri

Development Profile

İlk geliştirme ve local testing için uygun:

# Duplicate Detection Thresholds
INGEST_DUPLICATE_REPEAT_SUSPICIOUS_THRESHOLD=3
INGEST_DUPLICATE_REPEAT_STUCK_THRESHOLD=10

# Rate Limiting (packets per minute)
INGEST_RATE_SUSPICIOUS_PER_MINUTE=12
INGEST_RATE_FLOOD_PER_MINUTE=30

# Interval Analysis (divisors of expected interval)
INGEST_INTERVAL_SUSPICIOUS_DIVISOR=4
INGEST_INTERVAL_FLOOD_DIVISOR=10

# Payload & Request Limits
INGEST_MAX_PAYLOAD_SIZE_BYTES=16384
INGEST_REQUEST_TIMEOUT_MS=5000

# Redis Configuration
INGEST_REDIS_DEVICE_BUFFER_TTL_SECONDS=86400

Özellikler:

  • Tolerant threshold'lar (false positive'i minimize eder)
  • Yavaş timeout (debugging için)
  • Büyük payload limiti (test case'leri için)

Staging Profile

Production'a yakın ama test-friendly:

# Duplicate Detection - Prod'a yakın
INGEST_DUPLICATE_REPEAT_SUSPICIOUS_THRESHOLD=2
INGEST_DUPLICATE_REPEAT_STUCK_THRESHOLD=8

# Rate Limiting - Biraz gevşek
INGEST_RATE_SUSPICIOUS_PER_MINUTE=10
INGEST_RATE_FLOOD_PER_MINUTE=25

# Interval Analysis - Prod'a yakın
INGEST_INTERVAL_SUSPICIOUS_DIVISOR=4
INGEST_INTERVAL_FLOOD_DIVISOR=10

# Payload Limits - Testing için daha geniş
INGEST_MAX_PAYLOAD_SIZE_BYTES=32768
INGEST_REQUEST_TIMEOUT_MS=5000

# Redis - Prod'a yakın
INGEST_REDIS_DEVICE_BUFFER_TTL_SECONDS=86400

Özellikler:

  • Production davranışına yakın
  • Load testing için uygun tolerans
  • Monitoring setup'ı test etmek için hazır

Production Profile

Canlı trafik için optimized:

# Duplicate Detection - Sıkı
INGEST_DUPLICATE_REPEAT_SUSPICIOUS_THRESHOLD=3
INGEST_DUPLICATE_REPEAT_STUCK_THRESHOLD=10

# Rate Limiting - Aynı default (dashboard alarmları tarafından kontrol edilir)
INGEST_RATE_SUSPICIOUS_PER_MINUTE=12
INGEST_RATE_FLOOD_PER_MINUTE=30

# Interval Analysis - Sıkı
INGEST_INTERVAL_SUSPICIOUS_DIVISOR=4
INGEST_INTERVAL_FLOOD_DIVISOR=10

# Payload Limits - Sıkı
INGEST_MAX_PAYLOAD_SIZE_BYTES=16384

# Request Timeout - Kısa (latency optimize)
INGEST_REQUEST_TIMEOUT_MS=3000

# Redis - 24 saat (retention policy)
INGEST_REDIS_DEVICE_BUFFER_TTL_SECONDS=86400

Özellikler:

  • Kesin karar veriş (false negative risk mitigate edilir)
  • Hızlı timeout (latency optimize)
  • Standart payload boyutu

Configuration Loading

Application Startup

Uygulama başlangıcında ortam değişkenlerini okumalı ve default values ile fallback yapmalıdır:

// Pseudocode örneği (TypeScript/Node.js)
interface IngestConfig {
duplicate: {
suspiciousThreshold: number;
stuckThreshold: number;
};
rate: {
suspiciousPerMinute: number;
floodPerMinute: number;
};
interval: {
suspiciousDivisor: number;
floodDivisor: number;
};
http: {
maxPayloadSize: number;
requestTimeoutMs: number;
};
redis: {
deviceBufferTtlSeconds: number;
};
}

function loadConfig(): IngestConfig {
return {
duplicate: {
suspiciousThreshold: parseInt(
process.env.INGEST_DUPLICATE_REPEAT_SUSPICIOUS_THRESHOLD || '3'
),
stuckThreshold: parseInt(
process.env.INGEST_DUPLICATE_REPEAT_STUCK_THRESHOLD || '10'
),
},
rate: {
suspiciousPerMinute: parseInt(
process.env.INGEST_RATE_SUSPICIOUS_PER_MINUTE || '12'
),
floodPerMinute: parseInt(
process.env.INGEST_RATE_FLOOD_PER_MINUTE || '30'
),
},
interval: {
suspiciousDivisor: parseInt(
process.env.INGEST_INTERVAL_SUSPICIOUS_DIVISOR || '4'
),
floodDivisor: parseInt(
process.env.INGEST_INTERVAL_FLOOD_DIVISOR || '10'
),
},
http: {
maxPayloadSize: parseInt(
process.env.INGEST_MAX_PAYLOAD_SIZE_BYTES || '16384'
),
requestTimeoutMs: parseInt(
process.env.INGEST_REQUEST_TIMEOUT_MS || '5000'
),
},
redis: {
deviceBufferTtlSeconds: parseInt(
process.env.INGEST_REDIS_DEVICE_BUFFER_TTL_SECONDS || '86400'
),
},
};
}

const config = loadConfig();

Configuration Validation

Startup sırasında konfigürasyon mantıklılığını kontrol etmek gerekir (sanity checks).

Zorunlu Validasyon Kuralları

KuralGerekçeÖrnek
suspiciousThreshold < stuckThresholdSuspicious → stuck sırası3 < 10 ✅
suspiciousPerMinute < floodPerMinuteWarning → flood sırası12 < 30 ✅
suspiciousDivisor > floodDivisor1/4 > 1/10 (interval eşikleri)4 > 10 ❌
maxPayloadSize > 100HTTP body minumum uygun16384 > 100 ✅
requestTimeoutMs > 100Timeout minumum makul5000 > 100 ✅
deviceBufferTtlSeconds > 60Redis key minimum hayatta kalış86400 > 60 ✅

Fail-Fast Strategy

Herhangi bir validation hatası bulunursa, uygulama startup başarısız olmalıdır:

function validateConfig(config: IngestConfig): void {
const errors: string[] = [];

if (config.duplicate.suspiciousThreshold >= config.duplicate.stuckThreshold) {
errors.push(
`suspiciousThreshold (${config.duplicate.suspiciousThreshold}) ` +
`must be < stuckThreshold (${config.duplicate.stuckThreshold})`
);
}

if (config.rate.suspiciousPerMinute >= config.rate.floodPerMinute) {
errors.push(
`suspiciousPerMinute (${config.rate.suspiciousPerMinute}) ` +
`must be < floodPerMinute (${config.rate.floodPerMinute})`
);
}

if (config.interval.suspiciousDivisor <= config.interval.floodDivisor) {
errors.push(
`suspiciousDivisor (${config.interval.suspiciousDivisor}) ` +
`must be > floodDivisor (${config.interval.floodDivisor})`
);
}

if (config.http.maxPayloadSize < 100) {
errors.push(`maxPayloadSize must be >= 100 bytes`);
}

if (config.http.requestTimeoutMs < 100) {
errors.push(`requestTimeoutMs must be >= 100ms`);
}

if (config.redis.deviceBufferTtlSeconds < 60) {
errors.push(`deviceBufferTtlSeconds must be >= 60`);
}

if (errors.length > 0) {
console.error('Configuration validation failed:');
errors.forEach((e) => console.error(` - ${e}`));
process.exit(1); // Fail fast
}

console.log('Configuration validated successfully');
}

Eşikleri Belirlemek için İzlenecek Yol

1. Default Values ile Başla

İlk deployment'ta example değerler kullan (yukarıda sağlanan dev/staging/prod profilleri).

2. Operasyonel Veri Topla

En az 1 hafta gerçek trafikten veri topla:

  • Duplicate paket oranı
  • Cihaz başına paket sıklığı
  • Normal interval dağılımı
  • Network retry pattern'leri

3. İstatistikleri Analiz Et

Örnek metrikler:
- 0.001% → 0.005%: Duplicate rate (legitimate network hataları için normal)
- p50: 0.5 paket/dakika, p95: 2 paket/dakika, p99: 5 paket/dakika
- NTP sync burst: Birkaç cihaz aynı anda hızlı paketler gönderiyor
- Firmware bug: Spesifik bir model 10+ tekrar duplicate gönderiyor

4. Threshold'ları Ayarla

  • Suspicious: p95 + 20% margin
  • Flood: p99 × 3-5 (gerçek flood vs noise diff)
  • Stuck: Domain bilgisine göre (örn: device beklediğx max repeat = 7, threshold = 10)

5. False Positive Risk Değerlendir

Hangi threshold'da legitimate cihazlar yanlış olarak işaretlenecek?

  • NTP sync event'i 12+ paket/dakika göndereceği biliniyor → min 15 olsun
  • Tekil çipleme hatası 3 tekrar → suspicious threshold 2 yerine 3 olsun

6. Monitoring Dashboardı Kur

Threshold'ların gerçek dünyadaki etkisini izle:

  • False positive rate (yanlışlıkla flagged cihazlar)
  • Detection latency (sorun ile uyarı arasındaki zaman)
  • Threshold utilization (kaç cihaz ne kadar yakın threshold'a)

7. Dinamik Ayarlamalar

İlk ay içinde gerekirse weekly reviews yaparak threshold'ları ince ayarla.


Özet: Değişim Yönetimi

DurumYapılacak
Dev → Staging.env.staging ile threshold'ları sertleştir
Staging → Prod.env.production ile ultra-sıkı mode
Prod operasyonuThreshold değişiklikleri için change request + gradual rollout
Emergency rolloutHızlı threshold adjustment → monitoring + instant rollback ready

Ortam değişkenlerini kullanmak sayesinde zero-downtime configuration updates mümkün olur (greenfield redeployment öncesinde tanımlı değerlerle başla).

Monitoring Örneği: Grafana Dashboard

Aşağıdaki JSON, 8 key metric'i gösteren bir Grafana dashboard panel örneğidir (Prometheus veri kaynağı ile):

{
"dashboard": {
"title": "Qapu Ingest Service Metrics",
"panels": [
{
"title": "Ingest Latency (p95)",
"targets": [
{
"expr": "histogram_quantile(0.95, ingest_process_duration_ms)"
}
],
"alert": {
"conditions": [{"operator": "gt", "query": "A", "reducer": "avg", "type": "query", "evaluator": {"params": [500], "type": "gt"}}],
"message": "p95 latency > 500ms"
}
},
{
"title": "Raw DB Write Errors",
"targets": [{"expr": "rate(raw_db_write_errors[1m])"}],
"alert": {"conditions": [{"evaluator": {"params": [10], "type": "gt"}}], "message": "errors > 10/min"}
},
{
"title": "Duplicate Rate",
"targets": [{"expr": "rate(duplicate_packets[1m]) / rate(total_packets[1m])"}],
"alert": {"conditions": [{"evaluator": {"params": [0.05], "type": "gt"}}], "message": "dup rate > 5%"}
},
{
"title": "Flood Detections/Hour",
"targets": [{"expr": "rate(flood_warnings[1h])"}],
"alert": {"conditions": [{"evaluator": {"params": [5], "type": "gt"}}], "message": "floods > 5/hr"}
},
{
"title": "Stuck Devices Count",
"targets": [{"expr": "count(stuck_cihazlar)"}],
"alert": {"conditions": [{"evaluator": {"params": [10], "type": "gt"}}], "message": "stuck > 10"}
},
{
"title": "Kafka Emit Success Rate",
"targets": [{"expr": "1 - (rate(kafka_emit_errors[1m]) / rate(kafka_emit_total[1m]))"}],
"alert": {"conditions": [{"evaluator": {"params": [0.99], "type": "lt"}}], "message": "success < 99%"}
},
{
"title": "Redis Availability",
"targets": [{"expr": "redis_up{instance=\"ingest\"}"}],
"alert": {"conditions": [{"evaluator": {"params": [1], "type": "ne"}}], "message": "redis down"}
},
{
"title": "Requests per Second",
"targets": [{"expr": "rate(http_requests_total[1m])"}],
"thresholds": {"mode": "percentage", "steps": [{"color": "yellow", "value": 50}, {"color": "red", "value": 150}]}
}
]
}
}

Import Adımları:

  1. Grafana Home → Create → Import
  2. Yukarıdaki JSON'ı paste et
  3. Prometheus datasource seç
  4. Dashboard save et

Custom Alerting: Her panel'in alert rule'ının bakılması önerilir — threshold'ları ortamınız için ince ayarla (production → daha sıkı, staging → daha tolerant).