Razvoj

Mastering Microservices: Architecting for Predictable Performance

Ovladavanje mikroservisima: Arhitektura za predvidljive performanse

Mikrousluge ne stvaraju automatski performanse. One stvaraju granice: između baza koda, timova, baza podataka, mreža, načina otkaza i cjevovoda za implementaciju. Te granice mogu olakšati razvoj sustava, ali također mogu brzu lokalnu operaciju pretvoriti u spor lanac udaljenih poziva.

Predvidive performanse korisniji su cilj. Sustav koji je dosljedno odzivan pod očekivanim opterećenjem lakše je održavati od onoga koji je povremeno spektakularno brz, a povremeno neobjašnjiv. Arhitektura bi trebala učiniti latenciju, kapacitet i otkaze dovoljno vidljivima da se o njima može promišljati prije nego što ih kupci otkriju.

Započnite s granicama koje opravdavaju svoj trošak

Granica usluge nije granica mape. Trebala bi predstavljati područje s jasnim vlasništvom, koherentnim podatkovnim modelom i neovisnim razlogom za promjenu. Podjela PHP aplikacije na zasebne usluge samo zato što ima module često stvara distribuiranu složenost bez stvarne autonomije.

Prije izdvajanja usluge postavite praktično pitanje: što postaje neovisno implementabilno, skalabilno ili održivo? Radno opterećenje izvještavanja koje izvršava skupe upite može zaslužiti odvojeni kapacitet od transakcijskog tijeka naplate. Komponenta za obavijesti može imati koristi od asinkrone obrade. Malom pomoćniku za validaciju vjerojatno nije potrebna HTTP krajnja točka.

Svaki udaljeni poziv dodaje serijalizaciju, upravljanje vezama, mrežnu latenciju, ponašanje pri isteku vremena i novu ovisnost koju treba nadzirati. Održavajte sinkrone putanje zahtjeva kratkima. Ako API zahtjev prije povratka mora pozvati pet nizvodnih usluga, njegovu repnu latenciju određuju najsporija ovisnost i međudjelovanja svih njih.

Namjerno oblikujte kritičnu putanju

Započnite s operacijom koju korisnik čeka. Za krajnju točku narudžbe kritična putanja može provjeriti unos, rezervirati zalihu, zabilježiti narudžbu i vratiti odgovor o prihvaćanju. Slanje e-pošte, ažuriranje analitike, izrada računa i osvježavanje indeksa pretraživanja obično se ne moraju dogoditi prije tog odgovora.

Premjestite nebitan rad u asinkrone poruke tamo gdje je to sigurno učiniti. Cilj nije učiniti sve asinkronim; cilj je zaštititi putanju odgovora od rada koji se može dovršiti kasnije. Taj izbor zahtijeva jasna očekivanja o eventualnoj konzistentnosti. Ako kupac očekuje obavijest odmah, proizvod i API ugovor moraju opisati što „odmah” znači.

Držite orkestraciju blizu slučaja uporabe

API pristupnik trebao bi obrađivati pitanja poput autentikacije, usmjeravanja i ograničavanja stope. Ne bi smio postati skriveni dom poslovnih pravila i tijekova rada među uslugama. Isto tako, usluga ne bi trebala izvršavati široke fan-out pozive samo zato što povezani podaci postoje drugdje.

Dajte prednost eksplicitnom tijeku rada na razini aplikacije. Na primjer, usluga za narudžbe može trajno pohraniti narudžbu u stanju na čekanju i objaviti događaj nakon uspješnog završetka transakcije baze podataka. Usluga ispunjavanja zatim konzumira taj događaj i obavlja vlastiti rad. To čini vlasništvo i ponašanje pri ponovnom pokušaju jasnijima od krhkog lanca zahtjeva.

$order = $orderRepository->createPending($command);

$transactionManager->afterCommit(
    fn () => $eventBus->publish(new OrderPlaced($order->id()))
);

return new AcceptedOrderResponse($order->id());

Točan mehanizam varira, ali načelo ostaje stabilno: ne najavljujte rad drugim uslugama prije nego što je promjena izvora istine trajna.

Učinite isteke vremena, ponovne pokušaje i idempotentnost dijelom API-ja

Zahtjev bez isteka vremena neriješeno je obećanje. U PHP-u konfigurirajte eksplicitna vremena isteka za povezivanje i ukupno trajanje za odlazne HTTP klijente, upravljačke programe baza podataka i potrošače poruka. Istek vremena treba odabrati na temelju dostupnog proračuna latencije pozivatelja, a ne kopirati iz zadane vrijednosti.

Ponovni pokušaji mogu poboljšati otpornost na prolazne kvarove, ali neselektivni ponovni pokušaji pojačavaju prekide rada. Ponovni pokušaj sporog nizvodnog poziva tri puta kroz stotine istodobnih zahtjeva može iscrpiti skupove veza i otežati oporavak. Ponovno pokušavajte samo operacije koje je sigurno ponoviti, koristite ograničeno eksponencijalno odgađanje i prestanite pokušavati kada pozivatelj više nema vremena čekati.

  • Postavite rok za cijeli dolazni zahtjev.
  • Dodijelite manje vremenske proračune nizvodnim pozivima.
  • Ponovno pokušavajte prolazne kvarove samo kada je operacija idempotentna.
  • Upotrijebite ključ idempotentnosti za zapise pokrenute izvana, poput plaćanja ili stvaranja narudžbe.
  • Vratite smislen odgovor o neuspjehu umjesto čekanja da se svaka ovisnost oporavi.

Idempotentnost je posebno važna kada klijenti, pristupnici i radnici svi mogu ponovno pokušavati. Pohranite ključ s rezultirajućom operacijom ili odgovorom. Kada isti zahtjev ponovno stigne, vratite izvorni ishod umjesto stvaranja dupliciranog rada.

Neka vlasništvo nad podacima oblikuje strategiju baze podataka

Dijeljene baze podataka primamljive su jer su spajanja praktična. Međutim, s vremenom stvaraju povezanost kroz sheme, migracije, zaključavanja i nejasno vlasništvo. Usluga bi trebala posjedovati podatke koje zapisuje i izlagati potrebne informacije putem API-ja, događaja ili namjenski izrađenih modela za čitanje.

To ne znači kopirati svaku tablicu u svaku uslugu. Znači odabrati odgovarajući prikaz za svaki slučaj uporabe. Katalog proizvoda može objavljivati promjene koje grade lokalni indeks pretraživanja. Nadzorna ploča narudžbi može koristiti model za čitanje optimiziran za upite o statusu umjesto spajanja operativnih tablica kroz više usluga tijekom obrade zahtjeva.

Performanse baze podataka i dalje su važne. Indeksirajte stupce koji se koriste za selektivne filtre, spajanja unutar usluge i putanje sortiranja koje se stvarno izvršavaju. Pregledajte planove upita umjesto da pretpostavljate da indeks pomaže. Izbjegavajte neograničene skupove rezultata i koristite paginaciju temeljenu na pokazivaču kada se zapisi mogu mijenjati dok korisnici pregledavaju stranice.

Koristite kontejnere radi ponovljivosti, a ne ceremonije

Docker pomaže kada razvoj, testiranje i produkcija pokreću isti artefakt aplikacije s eksplicitnim ovisnostima. PHP spremnik trebao bi imati jasan postupak izgradnje, konfiguraciju prikladnu za produkciju i ne smije se oslanjati na zapisivi kôd aplikacije. Konfiguracija pripada okruženju ili upravljanom sustavu konfiguracije; tajne se ne bi smjele ugrađivati u slike.

Provjere zdravlja trebale bi odgovoriti na pravo pitanje. Provjera živosti pokazuje treba li proces ponovno pokrenuti. Provjera spremnosti pokazuje može li sigurno primati promet. Tretiranje privremenog problema s bazom podataka kao neuspjeha živosti može uzrokovati petlje ponovnog pokretanja; tretiranje nespremnog radnika kao zdravog može mu poslati posao koji ne može obraditi.

Mjerite ponašanje koje namjeravate kontrolirati

Rad na performansama počinje opažljivošću. Bilježite stopu zahtjeva, stopu pogrešaka, distribucije latencije, dubinu reda, propusnost radnika, korištenje veza baze podataka i kvarove ovisnosti. Prosjeci su korisni za široke trendove, ali prikrivaju spore zahtjeve koje korisnici primjećuju. Pratite percentile i povežite ih s krajnjom točkom, ovisnošću, verzijom implementacije i radnim opterećenjem.

Dosljedno koristite identifikator zahtjeva ili praćenja u zapisnicima pristupnika, zapisnicima PHP aplikacije, pozadinskim poslovima i odlaznim pozivima. Kada krajnja točka postane spora, korisno pitanje rijetko je „je li usluga spora?” Ono glasi: „koja je faza potrošila proračun i zašto?”

Arhitektura mikrousluga postaje predvidiva kada svaka usluga ima malu, razumljivu odgovornost i svaka interakcija ima eksplicitan trošak.

Gradite za mirno upravljanje

Najjači sustavi mikrousluga nisu oni s najviše usluga. To su sustavi u kojima razvojni inženjer može objasniti putanju zahtjeva, vlasništvo nad podacima, ponašanje pri ponovnom pokušaju i odgovor na neuspjeh bez crtanja labirinta.

Održavajte sinkronu putanju uskom. Svakoj ovisnosti dodijelite istek vremena. Učinite ponovljeni rad sigurnim. Jasno posjedujte podatke. Mjerite stvarno ponašanje pod opterećenjem. Te navike pretvaraju mikrousluge iz organizacijskog dijagrama u arhitekturu koja ostaje odzivna kada lake pretpostavke prestanu vrijediti.

Portret autora bloga

Mihajlo

Ja sam Mihajlo — programer vođen znatiželjom, disciplinom i stalnom željom da stvorim nešto smisleno. Dijelim uvide, tutorijale i besplatne usluge kako bih pomogao drugima da pojednostave svoj rad i rastu u svijetu softvera i umjetne inteligencije koji se neprestano razvija.