Fəsil 15 · 7 dəq oxu

Observability: sistemi görə bilmək

Observability: sistemi görə bilmək

Ch07-də SLO-lar yazdıq, ch11-də isə failure-lara qarşı pattern-lər qurduq. Hər ikisi bir fərziyyəyə söykənir: sistemin içində nə baş verdiyini görə bilirik. Gecə saat üçdə checkout yavaşlayanda on-call mühəndisin ilk sualı "nə xarabdır?" olur və bu suala cavab tapmaq çox vaxt problemi düzəltməkdən daha uzun çəkir. ən böyük hissəsi diaqnozdur.

Bu fəsil alət seçimi kimi yox, architectural qərar kimi izah edir: hansı siqnalları toplamaq, nəyi ölçmək, nəyə görə alert vermək və niyə bunu sonradan "əlavə etmək" çətindir.

Monitoring və observability

Monitoring əvvəlcədən bildiyimiz problemləri izləyir: disk dolubmu, error rate həddi keçibmi, service cavab verirmi? Dashboard və alert-lər qabaqcadan yazılmış suallara cavab verir.

isə sistemin quality attribute-udur (ch02-dəki cədvəldə var): xaricdən topladığımız siqnallara baxaraq əvvəlcədən təxmin etmədiyimiz suallara nə qədər tez cavab verə bilirik? "Niyə yalnız Android 14 istifadəçiləri, yalnız bir region-da, yalnız endirim kodu ilə ödəniş edəndə alır?" Bu sual üçün heç kim əvvəlcədən dashboard qurmayıb.

bir process və bir log faylı var. Distributed sistemdə bir istifadəçi request-i on service-dən, iki queue-dan və üç database-dən keçir. Ch11-də gördüyümüz kimi, ən pis failure-lar yavaşlıq və . Onlar heç bir komponentin öz dashboard-unda qırmızı görünmür; problem komponentlərin arasında olur.

Üç siqnal: log, metric, trace

üç növ telemetry üzərində qurulur və hər birinin öz qiyməti var.

Log-lar ayrı-ayrı event-lərin qeydidir. Ən zəngin kontekst onlardadır, amma ən baha siqnal da onlardır: həcm traffic ilə birlikdə xətti artır. Sərbəst mətnli log-lar yalnız insan oxuyanda faydalıdır. isə hər event-i sahələri olan obyekt kimi yazır (user_id, order_id, status, duration_ms). Belə log-larda axtarış etmək, filter-ləmək və aqreqasiya aparmaq mümkün olur. Xərci azaltmaq üçün uğurlu request-lərin log-larına tətbiq olunur, xətalar isə həmişə tam yazılır.

Metric-lər zaman üzrə aqreqasiya olunmuş rəqəmlərdir: request sayı, error rate, histogram-ı. Onlar ucuzdur, tez sorğulanır və alert üçün idealdır. Zəif tərəfləri isə detalı itirmələridir: metric "error rate 3%-dir" deyir, amma hansı request-lərin niyə uğursuz olduğunu demir.

Metric-lərin gizli tələsi cardinality-dir. Hər unikal kombinasiyası ayrıca time series yaradır. endpoint və status_code bir neçə yüz series verir. Ona user_id əlavə etsəniz, milyonlarla series alırsınız və metric sistemi ya çox bahalaşır, ya da yıxılır. Qayda belədir: sərhədsiz dəyərlər (user, request, session ID-ləri) metric-ə yox, log-a və trace-ə aiddir.

Trace-lər bir request-in sistem boyunca keçdiyi yolu göstərir: hansı service-lər çağırıldı, hər biri nə qədər vaxt apardı, harada gözləmə yarandı. Distributed sistemdə "vaxt harada itdi?" sualına yalnız onlar birbaşa cavab verir.

Siqnal seçimi alətdən yox, verməli olduğunuz suallardan başlayır:

SualƏsas siqnalNiyə
Nə qədər istifadəçi təsirləndi?Metric / Aqreqasiya olunmuş, ucuz, tarixçəsi uzun
pozuruqmu, budget nə sürətlə yanır?Metric ()Alert üçün stabil və sürətli
Checkout niyə yavaşdır?TraceVaxtın hansı hop-da itdiyini göstərir
Bu konkret request-ə nə oldu?Log + Tək event-in tam konteksti
Problem yalnız bir qrup istifadəçidədirmi? / trace atributlarıYüksək cardinality-li sahələrlə filter
sonra nə dəyişdi?Metric (versiyaya görə) + traceƏvvəl/sonra müqayisəsi
Bu node resursdan boğulurmu?Metric (USE)Saturation resurs səviyyəsində görünür

Hər siqnalın öz işi var, onları bir-birinə bağlayan isə ortaq identifikatorlardır.

Nəyi ölçmək: golden signals, RED və USE

Hər şeyi ölçmək siqnalı səs-küydə itirir. Google SRE kitabındakı başlanğıc üçün yaxşı çərçivədir:

  • — request-lər nə qədər vaxt aparır (uğurlu və uğursuzlar ayrıca, çünki sürətli 500 cavabı ortanı aldadıcı şəkildə yaxşılaşdırır).
  • Traffic — sistemə nə qədər yük gəlir (, message sayı).
  • Errors — uğursuz request-lərin nisbəti.
  • Saturation — resurs nə qədər doludur (CPU, memory, connection pool, queue uzunluğu).

RED (Rate, Errors, Duration) request emal edən service-lər üçündür və birbaşa istifadəçi təcrübəsini əks etdirir. USE (Utilization, Saturation, Errors) isə resurslar üçündür: disk, CPU, connection pool. RED "istifadəçi nə hiss edir?", USE isə "hansı resurs darboğazdır?" sualına cavab verir.

heç vaxt orta ilə ölçülməməlidir. Orta 80 ms olan service-də request-lərin 1%-i 3 saniyə çəkə bilər və on backend çağırışı edən səhifənin istifadəçiləri bu yavaş "tail"-ə tez-tez düşür. Percentile-lərə (p50, , ) baxın və onları histogram-dan hesablayın: instance-ların öz ortası riyazi cəhətdən mənasızdır.

Distributed tracing və correlation ID

Trace bir request-in tam yoludur. O, -lardan ibarətdir: hər bir iş vahididir (HTTP çağırışı, database sorğusu, queue-dan oxuma), başlanğıc və bitiş vaxtı, atributları və valideyn var. Span-lar birlikdə ağac əmələ gətirir və vaxtın harada itdiyini bir baxışda göstərir.

Bunun işləməsi üçün context propagation lazımdır: hər service gələn request-dən oxumalı və etdiyi hər çağırışa ötürməlidir. HTTP və bu header-lərlə edilir (W3C Trace Context standartı). Eyni ID log-lara da yazılır və beləcə üç siqnalı birləşdirir: trace-də yavaş tapır, həmin ID ilə log-larda xəta mesajını görürsünüz.

Bu sahədə de-fakto standart -dir: vendor-dan asılı olmayan API, SDK və telemetry protokolu. Onu seçmək backend-i sonradan dəyişmək imkanını saxlayır. Ch04-dəki dillə desək, bu, üçün .

Hər request-i trace etmək bahadır, ona görə tətbiq olunur. Head qərarı request-in əvvəlində verir (məsələn, 1%): sadə və ucuzdur, amma nadir xətaları çox vaxt qaçırır. Tail qərarı request bitəndən sonra verir: xətalı və yavaş trace-ləri saxlayır, normal olanların az hissəsini götürür. Daha dəyərlidir, amma bütün qərar verilənə qədər buffer-də saxlamaq üçün ayrıca infrastruktur tələb edir.

SLO əsaslı alerting

Klassik alert-lər səbəbə görə qurulur: "CPU 90%-i keçdi", "pod restart oldu". Onların çoxu istifadəçiyə təsir olmayanda belə gecə adamı oyadır. Nəticə alert fatigue-dur: komanda alert-lərə məhəl qoymamağı öyrənir və real incident səs-küydə itir.

Daha yaxşı yanaşma simptoma görə alert verməkdir: istifadəçi təcrübəsi pisləşirmi? Ch07-dəki SLO-lar bunun üçün hazır dildir. Sual "error rate həddi keçdimi?" yox, " nə sürətlə yanır?" olur. Bu sürət adlanır: 1 o deməkdir ki, budget düz pəncərənin sonunda tükənəcək.

99.9%, pəncərə 30 gündür, deməli 0.1%-dir. 30 gün 720 saatdır, yəni budget bərabər xərclənəndə saatda onun 1/720 hissəsi (≈0.139%) yanır. Son 1 saatda budget-in 2%-i yanıbsa, = 0.02 / (1/720) = 14.4 olur. Bu, error rate-in 14.4 × 0.1% = 1.44% olması deməkdir. Bu sürətlə bütün aylıq budget 720 / 14.4 = 50 saatda, yəni iki gündən bir az artıq müddətdə tükənəcək. Bu, gecə adamı oyatmağa dəyər.

Tək pəncərə ya gec reaksiya verir, ya da qısa dalğalanmalarda yalançı alert yaradır. Ona görə multi-window alert-lər istifadə olunur: məsələn, 1 saatlıq və 5 dəqiqəlik pəncərələrin ikisində də 14.4-dən yüksəkdirsə, page göndərilir. Qısa pəncərə problemin hələ davam etdiyini təsdiqləyir. Daha yavaş yanma (məsələn, 6 saatda budget-in 5%-i, 6) isə page yox, iş saatlarında baxılacaq ticket yaradır.

Əsas qayda: hər alert actionable olmalıdır. Alert gələndə on-call mühəndis konkret nəsə etməlidir. "Sadəcə məlumat üçün" alert dashboard-a aiddir, telefona yox.

Dashboard-lar və runbook-lar

Ch07-də gördük ki, artırmağın ən ucuz yolu çox vaxt kiçiltməkdir. isə aşkarlama, diaqnoz və bərpa mərhələlərindən ibarətdir. alert-i aşkarlamanı sürətləndirir, dashboard və runbook-lar isə diaqnozu.

Yaxşı incident dashboard-u bir suala üç dəqiqədə cavab verməyə kömək edir: problem haradadır? Yuxarıda SLI-lar və , altında service-in RED metric-ləri, daha aşağıda isə dependency-lər və resurslar (USE). Üzərində son deploy-lar və config dəyişiklikləri qeyd olunur, çünki incident-lərin böyük hissəsi dəyişiklikdən sonra başlayır.

Runbook hər alert-ə bağlı qısa sənəddir: bu alert nə deməkdir, ilk hansı qrafikə baxmalı, tipik səbəblər nədir və hansı təhlükəsiz addımlar var (, söndürmək, traffic-i başqa region-a keçirmək). Runbook-suz alert mühəndisdən gecə saat üçdə sistemi sıfırdan öyrənməyi tələb edir.

Observability architectural qərar kimi

sonradan "əlavə etmək" çətindir, çünki o, hər komponentdən keçən cross-cutting concern-dir. işləməsi üçün o, istisnasız hər hop-dan keçməlidir: bir köhnə service header-i ötürmürsə, trace orada qırılır. Asinxron sərhədlər daha çətindir: yazılan event-in metadata-sında trace context olmalıdır, əks halda consumer-in işi heç bir request-ə bağlanmır.

Ona görə platform səviyyəsində standartlaşdırılmalıdır və bu, layiq qərardır: ortaq telemetry kitabxanası, standart log sahələri, metric adlandırma qaydaları, propagation formatı və yeni service-lərin bunları default olaraq aldığı şablon. Ch05-dəki burada da işləyir: trace context ötürməyən service-i CI-da aşkarlamaq olar.

İki praktik məhdudiyyəti də nəzərə alın. Birincisi, xərc: telemetry asanlıqla infrastrukturun özündən baha başa gələ bilər. Ona büdcə ayırın, və log-ların saxlanma müddətini şüurlu seçin. İkincisi, sisteminin özü də -dir. Monitoring production ilə eyni cluster-də və eyni region-dadırsa, region yıxılanda alert-lər də susur. Alert sistemi izlədiyi sistemdən müstəqil olmalıdır və onun özü də xaricdən yoxlanmalıdır, məsələn, sadə "heartbeat" alert-i ilə: bu siqnal gəlməyəndə kimsə xəbər tutsun.

Hazırkı sisteminiz haqqında suallar

  1. Son incident-də diaqnoz nə qədər çəkdi? Cavabı tapmaq üçün hansı siqnal çatışmırdı?
  2. Bir istifadəçi request-ini ilə front-end-dən database-ə və asinxron consumer-lərə qədər izləyə bilirsinizmi? Zəncir harada qırılır?
  3. Son bir ayda gələn alert-lərin neçəsi konkret bir hərəkət tələb etdi? Qalanları niyə hələ də aktivdir?
  4. Monitoring sisteminiz production ilə eyni region-da yıxılsa, bundan necə və kim xəbər tutar?