Contorul de vizualizări care a transformat catalogul nostru într-un 502
Livrare
Pagina care listează fiecare kit pe care îl vindem a răspuns fiecărui vizitator cu un 502 Bad Gateway timp de aproximativ 41 de ore după lansare. Pagina proprie a fiecărui kit funcționa, pagina principală funcționa, checkout-ul funcționa. Partea defectă erau câteva linii care numărau vizualizările de pagini.
Bugul
Serverul magazinului nostru numără vizitele la paginile kiturilor. Pentru a afla pentru ce kit este o cerere, lua a doua parte a căii:
self._count_view(path.strip("/").split("/")[1] if path.count("/") >= 2 else "")
Pentru /kits/studio/ aceasta este studio. Pentru catalogul propriu-zis, /kits/, calea are două bare oblice, deci mecanismul de siguranță a lăsat-o să treacă, dar după eliminarea barelor oblice rămâne doar o parte, iar [1] a generat o eroare IndexError. Handler-ul este http.server standard din Python: o excepție în do_GET închide conexiunea fără răspuns, iar Cloudflare afișa vizitatorului un 502.
Remedierea este o funcție mică ce returnează un șir gol când partea lipsește. Contorul de vizualizări avea nevoie doar de numele kitului; nu trebuia niciodată să poată strica pagina pe care o număra.
De ce niciuna dintre verificările noastre nu a observat problema
- Monitorizarea disponibilității deschidea doar paginile principale. Pagina principală era în regulă.
- Pasul de lansare verifica fiecare kit livrat: pagina sa, redirecționarea către checkout, traseul plătit cap-coadă. Nu deschidea niciodată lista tuturor kiturilor.
- Analiticele nu puteau arăta problema. Codul care ar fi numărat vizitatorii catalogului era codul care se prăbușea. Logul serverului avea răspunsul de la început: 17 tracebacks în acele 41 de ore, fiecare o cerere, de la o persoană sau un crawler, care a primit o eroare în loc de pagină.
Ce s-a schimbat
- Fiecare pagină, din exterior, în fiecare oră. O sarcină mică citește sitemap-ul și deschide fiecare pagină în engleză și, la rând, una dintre celelalte 42 de limbi, prin Cloudflare ca un vizitator. Două rulări eșuate consecutive trimit un email; recuperarea trimite altul.
- Pasul de lansare deschide fiecare pagină în engleză după ce reconstruiește site-ul și refuză să se finalizeze dacă una nu răspunde cu 200.
- Paginile index contează ca pagini. Paginile care listează alte pagini sunt primele la care ajunge un vizitator și erau tocmai cele pe care nimeni nu le testase.
Concluzia
Activitățile auxiliare dintr-un request handler, cum ar fi numărarea, logarea sau urmărirea, nu trebuie să poată eșua niciodată requestul, iar o verificare a paginilor care acoperă doar paginile modificate recent ratează cele care fac legătura către ele. Watch-ul din Night Watch preia orice listă de pagini, fiecare cu textul pe care trebuie să îl conțină, nu doar paginile principale.