Go dispatcher
ADR-0026 §3. Push gönderimini (APNs, FCM, HMS, Web Push) Go servisine (services/dispatcher) taşır; render, sahiplenme ve sonuç uygulama worker'da kalır. İsteğe bağlıdır ve anında geri alınır: DISPATCHER_GO_CHANNELS…
docs/adr/0026-olcek-mimarisi.md. Push gönderimini (APNs, FCM, HMS, Web Push) Go servisine
(services/dispatcher) taşır; render, sahiplenme ve sonuç uygulama worker'da kalır. İsteğe bağlıdır ve anında geri
alınır: DISPATCHER_GO_CHANNELS boşken tüm gönderim TS sağlayıcılarıyla yapılır. Teknik ayrıntı ve köprü sözleşmesi:
services/dispatcher/README.md.
Etkinleştirme
- Ön koşul: Go servisi worker ile aynı
MASTER_KEY,DATABASE_URLveREDIS_URLdeğerlerini kullanır. Sunucu saatleri NTP ile eşit olmalı (son tarih karşılaştırması iki taraflıdır). - Servisi başlat:
- Compose:
docker compose --env-file .env.prod -f infra/compose/docker-compose.prod.yml --profile go-dispatcher up -d dispatcher - Kubernetes: chart'a dispatcher Deployment'ı eklenene kadar imaj
ghcr.io/exec0de/pushizo-dispatcherayrı Deployment olarak çalıştırılır (değerler aşağıda).
- Compose:
- Hazır olduğunu doğrula: konteyner sağlıklı (
/dispatcher healthcheck),GET :4002/readyz→ready; Redis'teZRANGE hs:dispatch-go:alive:ios_push 0 -1 WITHSCORESörnek adını gösterir. - Kanalları sırayla aç: worker-dispatch için
DISPATCHER_GO_CHANNELS=web_push(en düşük riskli) → izle → ekle (ios_push,android_push,hms_push,web_push). Worker yeniden başlatılır (değişken açılışta okunur). - İzle (en az bir kampanya döngüsü): aşağıdaki metrikler; teslimat oranı ve hata kodları önceki günle aynı olmalı.
DISPATCHER_GO_FALLBACK=true (varsayılan) iken canlı Go örneği yoksa batch TS sağlayıcısıyla gönderilir
(dispatcher_go_requests_total{outcome="fallback"}); Go servisi dağıtım sırasında kısa süre kapansa da gönderim durmaz.
false yapılırsa Go yokken batch'ler akışta bekler ve zaman aşımında geçici hata alıp yeniden denenir.
Geri dönüş
DISPATCHER_GO_CHANNELS= (boş) yapıp worker-dispatch'i yeniden başlatın: sonraki batch'ten itibaren TS sağlayıcıları
kullanılır. Akışta kalan istekler son tarihi geçince Go servisi tarafından gönderilmeden silinir; yanıt beklenirken
worker kapanırsa ilgili batch geçici hata olarak yeniden denenir (yinelenen bildirim üretmez). Go servisi ayrıca
durdurulabilir; kanal tek tek de geri alınabilir.
Metrikler
| Metrik | Kaynak | Anlam / eşik |
|---|---|---|
provider_send_total{provider,outcome} | Go (Go modundaki kanallar) / worker (TS modu) | Aynı ad ve etiketler; Go modunda worker yazmaz (çift sayım yok). auth ve invalid_token oranı önceki dönemle karşılaştırılır |
provider_latency_seconds{provider} | Go / worker | Batch gönderim süresi; p95 TS dönemine yakın veya altında olmalı |
dispatcher_go_requests_total{channel,outcome} | worker | ok; timeout > 0 ise Go servisi yetişemiyor/çalışmıyor; rejected sözleşme/sürüm uyuşmazlığı; fallback canlı örnek yok |
dispatcher_go_roundtrip_seconds{channel} | worker | XADD → yanıt süresi; DISPATCHER_GO_TIMEOUT_MS'e yaklaşıyorsa ölçekleyin |
dispatcher_go_batches_total{channel,outcome} | Go | ok; stale (son tarihi geçmiş istek, gönderilmedi), invalid, error (kimlik bilgisi/DB) |
dispatcher_go_inflight_batches{channel} | Go | DISPATCHER_MAX_BATCHES sınırına dayanıyorsa replika veya sınır artırılır |
Prometheus compose'da pushizo-dispatcher işiyle (DNS keşfi; servis yoksa hedef oluşmaz) toplar.
Sorun giderme
| Belirti | Olası neden | Yapılacak |
|---|---|---|
Açılışta aktif veri anahtarı MASTER_KEY ile çözülemedi | Go servisine farklı MASTER_KEY verilmiş | Worker/API ile aynı değeri verin (gizli yöneticiden) |
Teslimatlarda GO_DISPATCHER_TIMEOUT | Go servisi kapalı (yedek kapalı), aşırı yük, Redis gecikmesi | readyz, dispatcher_go_inflight_batches; replika ekleyin veya DISPATCHER_MAX_BATCHES artırın; acilse geri dönüş |
GO_CREDENTIALS / GO_DATABASE hata kodları | Go servisi satırı okuyamıyor/çözemiyor (DB erişimi, RLS rolü, anahtar) | Servis logu (kimlik bilgisi çözülemedi); kanal invalid yapılmaz, batch'ler yeniden denenir |
GO_CONFIG_CHANGED | Gönderim sırasında kanal yapılandırması değişti | Kendiliğinden düzelir (yeniden denemede yeni yapılandırma) |
GO_DISPATCHER_REJECTED | Worker ve Go servis sürümleri farklı protokol konuşuyor | İki bileşeni aynı sürüme getirin |
stale artıyor | Worker'lar zaman aşımına uğramış istekleri bırakıyor; saat kayması | NTP, DISPATCHER_GO_TIMEOUT_MS, Go kapasitesi |
hs:dispatch-go:* akışı büyüyor | Go servisi kanal akışını okumuyor (DISPATCHER_CHANNELS eksik) | Kanal listesini düzeltin; akış ~100k girdide kırpılır |
Kimlik bilgisi Redis'e yazılmaz; akış girdilerinde yalnızca render edilmiş içerik, cihaz belirteci ve config_id bulunur.
Go servisi channel_configs satırını RLS etkin işlemde (app.current_app_id) ve app_id filtresiyle okur.
Kubernetes değerleri (chart'a eklenecek)
Dispatcher Deployment'ı için: imaj pushizo-dispatcher, port 4002 (/healthz liveness, /readyz readiness,
/metrics ServiceMonitor), ortam DATABASE_URL, REDIS_URL, MASTER_KEY (ExternalSecret), NODE_ENV=production,
DISPATCHER_CHANNELS, DISPATCHER_MAX_BATCHES, WEB_PUSH_EXTRA_HOSTS; terminationGracePeriodSeconds: 45,
readOnlyRootFilesystem: true, runAsNonRoot (UID 65532); NetworkPolicy çıkışı: Postgres, Redis ve sağlayıcılar
(443). Worker-dispatch için DISPATCHER_GO_CHANNELS, DISPATCHER_GO_TIMEOUT_MS, DISPATCHER_GO_FALLBACK.
ClickHouse analitik deposu ve Kafka ingest
ADR-0026. İkisi de isteğe bağlıdır: ayarlanmadığında sistem Postgres + BullMQ ile eskisi gibi çalışır.
Yük testi (k6-operator, dağıtık)
v2 Faz 16 madde 5 (docs/plan/10). Manifestler infra/load/, betikler tests/load/. Tek makineden koşulan Faz 14 prosedürü (10k olay/sn, 1M fan-out) tests/load/README.md içindedir; bu runbook Kubernetes'te dağıtık koşuyu…