Blog

Mga Alert na Isang Beses Lang Nagpapadala, Hindi Isang Beses Bawat Server

Isa sa mga operational alert namin, ang "low credits" para sa na-publish na app ng isang builder, ay dapat umabot sa amin nang hindi lalampas sa isang beses kada araw. Isang hapon, dumating ito nang limang beses. Ang dahilan: inaalala ng bawat kopya ng API namin sa sarili nitong memory kung aling alert ang naipadala na, kaya dalawang server ang nagpadala nito nang dalawang beses, at sa bawat deploy, nabubura ang memory na iyon at nagpapadala na naman sila. Ganoon din ang nangyari sa isang background job na nagsagawa ng trabaho nang dalawang beses. Ngayon, nagkakasundo na ang dalawa sa pamamagitan ng shared store, at parehong pumapanig sa ligtas na panig kapag hindi maabot ang store na iyon.

Ang sintomas

Nagpapadala ang Mythex ng alert sa team kapag may kailangang tingnan: down ang isang service, natigil ang isang job, o mababa na ang credit balance ng builder habang naka-publish ang app niya. May dedupe window ang bawat alert, isang panahon kung kailan isang beses lang ipinapadala ang parehong alert. Para sa low-credits alert, 24 oras ang window na iyon.

Limang kopya ng parehong alert sa isang hapon ay nangangahulugang hindi gumagana ang window. Mas masama pa, dumating ang mga ito nang pares-pares, mga 11 minuto ang pagitan.

Bakit nangyari ito

Sa memory itinago ng alerts package namin ang dedupe: isang talaan ng "alert key → kailan ito huling ipinadala", sa loob ng tumatakbong process. Gumagana iyon kapag iisa lang ang process na hindi nagre-restart. Pero wala sa dalawa ang production:

  • Dalawang API replica. Dalawang kopya ng API ang tumatakbo sa production. May kanya-kanyang talaan ang bawat isa, kaya bawat isa ay nagpadala ng alert nang isang beses. Iyon ang mga pares.
  • Mga deploy. Pinapalitan ng bawat deploy ang dalawang replica ng bagong process na may walang laman na talaan. Pagkatapos ng deploy, lumabas ulit ang alert na para bang hindi pa ito nagpapadala kailanman.

Ang ~11 minutong pagitan ng dalawang alert sa bawat pares ay galing sa job na nagtataas ng alert na ito. Tumatakbo ito sa dalawang replica at kumukuha ng lock, kaya salitan silang nananalo, at itinataas ng bawat isa ang alert kapag dumating ang kanyang turn.

May pangalawa, mas tahimik na bug sa parehong code. Para hindi lumaki nang walang hanggan ang talaan, nililinis nito ang sarili kapag umabot sa 500 key: binubura ang bawat entry na mas luma sa 15 minuto, anuman ang window nito. Sa ilalim ng load, isang 24-oras na dedupe ay tumatagal lang ng isang kapat ng oras.

Ang ayos

Isang shared na talaan bawat alert

Bago magpadala ang API ng alert, ina-claim na nito ang dedupe key ng alert sa Redis, isang shared na in-memory store na kinakausap ng dalawang replica at hindi nagre-restart kapag nag-restart ang API. Ang claim ay iisang operasyon: "itakda ang key na ito kung wala pa, at i-expire ito pagkatapos ng window." Ang replica na unang nakakuha ng claim ang nagpapadala ng alert; nakikita ng isa na okupado na ang key at tahimik na lang. Ang bagong process pagkatapos ng deploy ay makikitang nandoon pa rin ang key.

Galing ang key at window sa parehong patakaran na ginagamit ng alerts package, na ngayon ay shared na ng dalawang layer, kaya hindi sila magkakaiba ng pananaw sa kung ano ang "parehong alert".

Pumanig sa fail open, hindi fail closed

Ang pinakamahalagang desisyon ay kung ano ang gagawin kapag hindi maabot ang Redis. Pinili naming ipadala pa rin ang alert. Kung down ang Redis, o hindi sumagot sa loob ng 1.5 segundo, lalabas pa rin ang alert. Ang dobleng alert ay ingay lang. Ang nawalang alert ay taong hindi naabisuhan.

Hindi kailanman pinipigilan ng dedupe ang pinakaseryosong alert, ang P0.

Bawat entry ay may sariling window

Sa sarili nitong in-memory dedupe ng alerts package, ngayon ay nakatala na sa bawat entry kung kailan magtatapos ang window nito, at tanging ang mga entry na tapos na ang window ang tinatanggal ng paglilinis. Mananatili ang 24-oras na key nang 24 oras, gaano man karaming ibang alert ang dumating.

Ang parehong bug, sa ibang lugar

Ang parehong pattern ay nagpadoble rin ng isang bahagi ng background work: isang reconciliation job na nagpapanatiling tugma ang talaan namin ng status ng bawat workspace sa talaan ng sandbox provider namin. Bawat pass nito ay naglilista ng bawat sandbox sa account (libu-libo sa production, mga limang segundo) pati bawat tumatakbo o naka-pause na proyekto. Tumatakbo ito sa dalawang replica tuwing dalawang minuto.

Idempotent ang mga write nito, ibig sabihin, ang pagtakbo nito nang dalawang beses ay nagbibigay ng parehong resulta gaya ng isang beses, kaya walang nasira. Dobleng trabaho lang ito. Ngayon, bawat dalawang minutong window ay ina-claim sa Redis sa paraang ginawa na ng usage meters namin para sa kanila, at ang replica lang na nakakuha ng claim ang nagpapatakbo ng pass. Kung hindi maabot ang Redis, tatakbo pa rin ang pass: ang paggawa ng trabaho nang dalawang beses ay hindi nakapipinsala, pero ang hindi paggawa nito ay nakapipinsala.

Paano namin ito sinubukan

Ginagaya ng mga test ang totoong setup. Nilo-load nila ang alert module nang dalawang beses, bilang dalawang hiwalay na "replica", tinuturo ang dalawa sa iisang shared store, nagtataas ng parehong alert mula sa bawat isa, at pagkatapos ay naglo-load ng ikatlong bagong kopya para tumayong "pagkatapos ng deploy" at itinataas ulit ito. Isa lang ang alert na naipadala. Sinusuri ng ibang test na naipapadala pa rin ang alert ng ibang builder, na naipapadala ang P0 mula sa parehong replica, at na naipapadala pa rin ang alert kapag down o natigil nang lampas sa timeout ang store. May sariling test ang ayos sa prune: nabubuhay ang 24-oras na key kahit dumating ang 600 iba pang alert makalipas ang 20 minuto.

Para sa reconciliation job, ang dalawang replica na sabay na tumutick, kasama ang ikatlong tick sa parehong window, ay gumagawa ng iisang listing.

Ang natutunan namin

  • Per process ang state sa memory. Ang anumang dapat maging totoo sa lahat ng server, gaya ng "naipadala na minsan" o "tumakbo na minsan", ay kailangang nasa lugar na pinagsasaluhan nila.
  • Ang deploy ay restart. Ang state na nabubuhay lang hanggang sa susunod na restart ay hindi nabubuhay sa isang normal na araw ng trabaho.
  • Magpasya kung paano pumapalya. Para sa mga alert, ang pagkaka-down ng shared store ay dapat magdulot ng mas maraming alert, hindi mas kaunti.
  • Hanapin ang pattern, hindi lang ang instance. Ang alert ang malakas na kaso; ang dobleng reconciliation job ang parehong bug, tahimik na nagkakagastos ng trabaho.

Wala sa mga ito ang nakikita mula sa loob ng Mythex. Para pa sa kung paano namin pinananatiling matatag ang platform, tingnan ang paano namin nabawasan ang deploys sa zero na 502 error at ang nawawalang swap file. Kung bago ka pa sa ideya ng pagpapatakbo ng higit sa isang kopya ng isang service, sakop ng gabay namin tungkol sa ano ang server ang mga pangunahing kaalaman.

Mythex · Pricing · Gumawa ng kahit ano gamit ang AI · Mga template ng website at app · Paghahambing ng Mythex · Glosaryo ng paggawa ng app gamit ang AI · Mga libreng tool sa paggawa ng app gamit ang AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)