Šta znamo o mikroservisima

Zdravo! Moje ime je Vadim Madison, vodim razvoj Avito sistemske platforme. Više puta je rečeno kako mi u kompaniji prelazimo sa monolitne arhitekture na mikroservis. Vrijeme je da podijelimo kako smo transformirali našu infrastrukturu kako bismo izvukli maksimum iz mikrousluga i ne izgubili se u njima. Kako nam PaaS ovdje pomaže, kako smo pojednostavili implementaciju i sveli kreiranje mikroservisa na jedan klik - čitajte dalje. Nije sve o čemu pišem u nastavku u potpunosti implementirano u Avito, dio toga je način na koji razvijamo našu platformu.

(I na kraju ovog članka, govorit ću o prilici da uđem u trodnevni seminar stručnjaka za mikroservisnu arhitekturu, Chrisa Richardsona).

Šta znamo o mikroservisima

Kako smo došli do mikroservisa

Avito je jedan od najvećih oglasnika na svijetu, objavljuje više od 15 miliona novih oglasa dnevno. Naš backend prihvata više od 20 hiljada zahteva u sekundi. Sada imamo nekoliko stotina mikroservisa.

Mi gradimo mikroservisnu arhitekturu više od godinu dana. Kako tačno - naše kolege detaljno rekao u našoj sekciji na RIT++ 2017. Na CodeFest-u 2017 (vidi видео), Sergej Orlov i Mihail Prokopčuk su detaljno objasnili zašto nam je uopšte bio potreban prelazak na mikroservise i kakvu je ulogu tu odigrao Kubernetes. Pa, sada činimo sve da minimiziramo troškove skaliranja koji su svojstveni takvoj arhitekturi.

U početku nismo kreirali ekosistem koji bi nam sveobuhvatno pomogao u razvoju i lansiranju mikroservisa. Samo su prikupili pametna rješenja otvorenog koda, pokrenuli ih kod kuće i ponudili programeru da se s njima pozabavi. Kao rezultat toga, otišao je na desetak mjesta (kontrolne ploče, interni servisi), nakon čega je ojačao želju da isječe kod na stari način, u monolit. Zelena boja na dijagramima ispod označava ono što programer na ovaj ili onaj način radi vlastitim rukama, žuta boja označava automatizaciju.

Šta znamo o mikroservisima

Sada, u PaaS CLI uslužnom programu, jedan tim kreira novu uslugu, a još dva dodaju novu bazu podataka i implementiraju je u Stage.

Šta znamo o mikroservisima

Kako prevladati eru "fragmentacije mikroservisa"

Uz monolitnu arhitekturu, radi konzistentnosti promjena u proizvodu, programeri su bili primorani da shvate šta se dešava sa njihovim susjedima. Kada radite na novoj arhitekturi, konteksti usluga više ne ovise jedan o drugom.

Osim toga, da bi mikroservisna arhitektura bila efikasna, potrebno je uspostaviti mnoge procese, i to:

• sječa;
• praćenje zahtjeva (Jaeger);
• agregiranje grešaka (Sentry);
• statusi, poruke, događaji iz Kubernetesa (Event Stream Processing);
• granica trke / prekidač (možete koristiti Hystrix);
• kontrola servisne povezanosti (koristimo Netramesh);
• monitoring (Grafana);
• montaža (TeamCity);
• komunikacija i obavještavanje (Slack, email);
• praćenje zadataka; (Jira)
• priprema dokumentacije.

Kako bismo osigurali da sistem ne izgubi integritet i da ostane efikasan tokom skaliranja, preispitali smo organizaciju mikroservisa u Avitu.

Kako upravljamo mikrouslugama

Avito pomaže da se provede jedna "stranačka politika" među brojnim mikroservisima:

  • podjela infrastrukture na slojeve;
  • koncept platforme kao usluge (PaaS);
  • praćenje svega što se dešava sa mikroservisima.

Nivoi apstrakcije infrastrukture uključuju tri sloja. Idemo od vrha do dna.

A. Gornja - servisna mreža. Isprva smo isprobali Istio, ali se pokazalo da koristi previše resursa, što je preskupo za naše količine. Stoga je viši inženjer u arhitektonskom timu Aleksandar Lukjančenko razvio vlastito rješenje − Netramesh (dostupan u Open Source), koji trenutno koristimo u proizvodnji i koji troši nekoliko puta manje resursa od Istia (ali ne radi sve čime se Istio može pohvaliti).
B. Srednji - Kubernetes. Na njemu postavljamo i upravljamo mikroservisima.
C. Dno - goli metal. Ne koristimo oblake i stvari kao što je OpenStack, već se nalazimo u potpunosti na golom metalu.

Svi slojevi su kombinovani PaaS. A ova platforma se zauzvrat sastoji od tri dijela.

I. Generatori, kojim se upravlja preko CLI uslužnog programa. Ona je ta koja pomaže programeru da kreira mikroservis na pravi način i uz minimalan trud.

II. Konsolidovani kolektor sa kontrolom svih instrumenata preko zajedničke kontrolne table.

III. skladištenje. Povezuje se s planerima koji automatski postavljaju okidače za smislene radnje. Zahvaljujući takvom sistemu, ni jedan zadatak se ne propušta samo zato što je neko zaboravio staviti zadatak u Jira. Za to koristimo interni alat pod nazivom Atlas.

Šta znamo o mikroservisima

Implementacija mikroservisa u Avitu također se provodi prema jednoj shemi, što pojednostavljuje kontrolu nad njima u svakoj fazi razvoja i izdavanja.

Kako funkcionira standardni cevovod razvoja mikroservisa

Generalno, lanac kreiranja mikroservisa izgleda ovako:

CLI-push → Kontinuirana integracija → Bake → Deploy → Vještački testovi → Canary testovi → Testiranje stiskanja → Proizvodnja → Održavanje.

Prođimo kroz to upravo ovim redom.

CLI-push

• Kreiranje mikroservisa.
Dugo smo se borili da naučimo svakog programera kako da napravi mikroservise. Uključujući i napisao detaljna uputstva u Confluence. Ali šeme su se mijenjale i dopunjavale. Rezultat - usko grlo je formirano na početku puta: bilo je potrebno mnogo više vremena za pokretanje mikroservisa nego što je dozvoljeno, a ipak je često bilo problema prilikom njihovog kreiranja.

Na kraju smo napravili jednostavan CLI uslužni program koji automatizira osnovne korake za kreiranje mikroservisa. U stvari, zamjenjuje prvi git push. Evo šta ona tačno radi.

- Kreira servis prema šablonu - korak po korak, u "wizard" modu. Imamo šablone za glavne programske jezike u Avito backendu: PHP, Golang i Python.

- Jedna komanda raspoređuje lokalno razvojno okruženje na određenoj mašini - Minikube se podiže, Helm grafikoni se automatski generišu i pokreću u lokalnom kubernetesu.

— Povezuje potrebnu bazu podataka. Programer ne mora znati IP, login i lozinku da bi dobio pristup bazi podataka koja mu je potrebna - barem lokalno, barem u fazi, barem u produkciji. Štaviše, baza podataka se odmah postavlja u konfiguraciji otpornoj na greške i sa balansiranjem.

- Izvodi samu montažu. Recimo da je programer ispravio nešto u mikroservisu preko svog IDE-a. Uslužni program vidi promjene u sistemu datoteka i, na osnovu njih, ponovo gradi aplikaciju (za Golang) i ponovo pokreće. Za PHP, jednostavno prosljeđujemo direktorij unutar kocke i tamo se ponovno učitavanje uživo dobiva „automatski“.

- Generiše autotestove. U obliku praznina, ali sasvim upotrebljivo.

• Uvesti mikroservis.

Nekada je bilo malo turobno implementirati mikroservis kod nas. Obavezno potrebno:

I. Dockerfile.

II. Config.
III. Helm-chart, koji je sam po sebi glomazan i uključuje:

- same karte;
- šabloni;
- specifične vrijednosti ​​uzimajući u obzir različita okruženja.

Otklonili smo bol prerade Kubernetes manifesta i sada su oni automatski generisani. Ali što je najvažnije, pojednostavili smo implementaciju do krajnjih granica. Od sada, imamo Dockerfile, a programer zapisuje cijelu konfiguraciju u jednu kratku app.toml datoteku.

Šta znamo o mikroservisima

Da, iu samom app.toml, sada postoji pitanje za minut. Propisujemo gdje koliko kopija servisa treba podići (na dev-serveru, na stagingu, na produkciji), označavamo njegove zavisnosti. Obratite pažnju na veličinu linije = "small" u bloku [engine]. Ovo je ograničenje koje će biti dodijeljeno usluzi putem Kubernetesa.

Dalje, na osnovu konfiguracije, svi potrebni Helm-karti se automatski generišu i kreiraju veze sa bazama podataka.

• Osnovna validacija. Takve provjere su također automatizirane.
Potrebno je pratiti:
- postoji li Dockerfile;
- postoji li app.toml;
- Ima li dokumentacije?
— da li po redu zavisnosti;
— da li su postavljena pravila upozorenja.
Do posljednje točke: vlasnik usluge sam određuje koje metrike proizvoda treba pratiti.

• Priprema dokumentacije.
Još uvijek problematično područje. Čini se da je to najočitija, ali u isto vrijeme rekord "često zaboravljen", a samim tim i ranjiva karika u lancu.
Neophodno je da dokumentacija bude za svaki mikroservis. Uključuje sljedeće blokove.

I. Kratak opis usluge. Samo nekoliko rečenica o tome šta radi i čemu služi.

II. Veza na arhitektonski dijagram. Važno je da je na prvi pogled lako razumjeti, na primjer, koristite li Redis za keširanje ili kao glavno skladište podataka u trajnom načinu rada. U Avitu, za sada, ovo je veza za Confluence.

III. runbook. Kratak vodič za pokretanje usluge i suptilnosti rukovanja njome.

IV. FAQ, gdje bi bilo dobro predvidjeti probleme sa kojima se vaše kolege mogu susresti u radu sa servisom.

V. Opis krajnjih tačaka API-ja. Ako odjednom niste naveli destinacije, gotovo sigurno će to platiti kolege čije su mikroservise povezane s vašima. Sada koristimo Swagger za ovo i naše rješenje koje se zove brief.

VI. Etikete. Ili markeri koji pokazuju kom proizvodu, funkcionalnosti, strukturnom dijelu kompanije pripada usluga. Pomažu da se brzo shvati, na primjer, da li vidite funkcionalnost koju su vaše kolege uvele za istu poslovnu jedinicu prije tjedan dana.

VII. Vlasnik ili vlasnici usluge. U većini slučajeva, on - ili oni - mogu se automatski odrediti pomoću PaaS-a, ali za osiguranje, zahtijevamo od programera da ih navede i ručno.

Konačno, dobra je praksa provoditi preglede dokumentacije, slično pregledima koda.

Kontinuirana integracija

  • Priprema repozitorija.
  • Kreiranje cjevovoda u TeamCity-u.
  • Dodjela prava.
  • Potražite vlasnike usluga. Evo hibridne šeme - ručno označavanje i minimalna automatizacija iz PaaS-a. Potpuno automatska šema ne uspijeva kada se usluge prenesu na podršku u drugom razvojnom timu ili, na primjer, ako programer usluge odustane.
  • Registracija servisa u Atlasu (vidi gore). Sa svim svojim vlasnicima i ovisnostima.
  • Provjera migracija. Provjeravamo ima li među njima potencijalno opasnih. Na primjer, u jednom od njih se pojavljuje alter tablica ili nešto drugo što može narušiti kompatibilnost šeme podataka između različitih verzija usluge. Tada se migracija ne vrši, već se stavlja u pretplatu - PaaS treba da signalizira vlasniku usluge kada postane bezbedno da je primeni.

Peći

Sljedeća faza je pakovanje usluga prije implementacije.

  • Montaža aplikacije. Prema klasicima - u Docker slici.
  • Generiranje Helm karata za samu uslugu i povezane resurse. Uključujući baze podataka i keš memorije. Kreiraju se automatski u skladu sa app.toml konfiguracijom koja je generirana u CLI-push fazi.
  • Kreiranje tiketa za administratore za otvaranje portova (kada je potrebno).
  • Izvođenje jediničnih testova i izračunavanje pokrivenosti koda. Ako je pokrivenost koda ispod navedene granične vrijednosti, tada, najvjerovatnije, usluga neće ići dalje - do implementacije. Ako je na granici prihvatljivog, tada će se servisu dodijeliti koeficijent "pesimiziranja": tada, ako ne dođe do poboljšanja indikatora tokom vremena, programer će dobiti obavijest da nema napretka u pogledu testova ( i trebalo bi nešto učiniti po tom pitanju).
  • Obračunavanje ograničenja memorije i CPU-a. U osnovi, mi pišemo mikroservise u Golangu i pokrećemo ih u Kubernetesu. Dakle, jedna suptilnost povezana sa značajkom Golang jezika: po defaultu, sve jezgre na mašini se koriste pri pokretanju, ako eksplicitno ne postavite GOMAXPROCS varijablu, a kada se nekoliko takvih servisa pokrene na istom stroju, oni počinju da se takmiče za resurse, ometajući jedni druge. Grafikoni ispod pokazuju kako se mijenja vrijeme izvršenja ako se aplikacija pokreće bez sukoba iu načinu utrke resursa. (Izvori grafikona su ovdje).

Šta znamo o mikroservisima

Vrijeme izvršenja, manje je bolje. Maksimalno: 643ms, minimalno: 42ms. Fotografija se može kliknuti.

Šta znamo o mikroservisima

Vrijeme je za operaciju, manje je bolje. Maksimalno: 14091 ns, minimalno: 151 ns. Fotografija se može kliknuti.

U fazi pripreme sklopa, ovu varijablu možete postaviti eksplicitno ili možete koristiti biblioteku automaxprocs od momaka iz Ubera.

Razviti

• Provjera konvencija. Prije nego što počnete isporučivati ​​servisne verzije u predviđena okruženja, morate provjeriti sljedeće:
- API krajnje tačke.
— Korespondencija odgovora API krajnjih tačaka na šemu.
- Format dnevnika.
- Postavljanje zaglavlja za zahtjeve servisu (sada to radi netramesh)
- Postavljanje markera vlasnika prilikom slanja poruka na sabirnicu (sabirnica događaja). Ovo je neophodno za praćenje povezanosti usluga putem sabirnice. Na sabirnicu možete slati i idempotentne podatke koji ne povećavaju povezanost usluga (što je dobro), i poslovne podatke koji poboljšavaju povezanost usluga (što je jako loše!). A u trenutku kada ova povezanost postane problem, razumijevanje ko piše i čita sabirnicu pomaže da se usluge pravilno odvoje.

Za sada nema mnogo konvencija u Avitu, ali njihov se fond širi. Što je više takvih sporazuma u formi koja je razumljiva i pogodna za tim, lakše je održavati konzistentnost između mikroservisa.

Sintetički testovi

• Testiranje zatvorene petlje. Za to sada koristimo open source hoverfly.io. Prvo bilježi stvarno opterećenje usluge, a zatim - samo u zatvorenoj petlji - emulira.

• Testiranje na stres. Trudimo se da sve usluge dovedemo do optimalnog učinka. I sve verzije svake usluge bi trebale biti podvrgnute testiranju opterećenja - tako da možemo razumjeti trenutne performanse usluge i razliku u odnosu na prethodne verzije iste usluge. Ako je nakon ažuriranja usluge njegova izvedba pala za jedan i pol puta, to je jasan signal za njegove vlasnike: morate ukopati u kod i ispraviti situaciju.
Polazimo od prikupljenih podataka, na primjer, kako bismo pravilno implementirali automatsko skaliranje i, na kraju, razumjeli općenito koliko je usluga skalabilna.

Tokom testiranja opterećenja provjeravamo da li potrošnja resursa zadovoljava postavljena ograničenja. I fokusiramo se prvenstveno na ekstreme.

a) Gledamo ukupno opterećenje.
- Premala - najvjerovatnije nešto uopće ne radi ako opterećenje naglo padne nekoliko puta.
- Prevelika - potrebna je optimizacija.

b) Pogledajte RPS cutoff.
Ovdje gledamo razliku između trenutne verzije i prethodne i ukupan broj. Na primjer, ako servis proizvodi 100 rps, onda je ili loše napisano, ili je to njegova specifičnost, ali u svakom slučaju, to je razlog da se servis pogleda izbliza.
Ako, naprotiv, ima previše RPS-a, onda je, možda, neka vrsta greške i neke od krajnjih tačaka prestale da izvršavaju korisni teret, ali samo neke return true;

Kanarski testovi

Nakon položenih sintetičkih testova, pokrećemo mikroservis na malom broju korisnika. Počinjemo pažljivo, sa malim udjelom namijenjene publike usluge - manje od 0,1%. U ovoj fazi vrlo je važno da se u monitoring unesu ispravne tehničke i proizvodne metrike kako bi što brže pokazale problem u servisu. Minimalno vrijeme testiranja kanarinca je 5 minuta, a glavno 2 sata. Za složene usluge postavljamo vrijeme u ručnom načinu rada.
Analiziramo:
- metrike specifične za jezik, posebno, php-fpm radnici;
— greške u Sentryju;
— statusi odgovora;
— vrijeme odziva (vrijeme odgovora), tačno i prosječno;
— latencija;
- izuzeci, obrađeni i neobrađeni;
- metrike proizvoda.

Testiranje stiskanja

Squeeze Testing se također naziva testiranjem "stiskanja". Naziv tehnike uveden je u Netflix. Njegova suština je da prvo ispunimo jednu instancu stvarnim prometom do stanja kvara i tako postavimo njenu granicu. Zatim dodajemo još jednu instancu i učitavamo ovaj par - opet do maksimuma; vidimo njihov plafon i deltu sa prvim stiskom. I tako povezujemo jednu instancu po koraku i izračunavamo obrazac u promjenama.
Podaci o testovima putem „stiskanja“ također se slijevaju u zajedničku bazu podataka metrika, gdje njima ili obogaćujemo rezultate umjetnog opterećenja, ili čak zamjenjujemo „sintetiku“.

Proizvodnja

• Skaliranje. Uvođenjem usluge u proizvodnju, pratimo kako se ona povećava. Istovremeno, praćenje samo CPU indikatora, prema našem iskustvu, nije efikasno. Automatsko skaliranje s RPS benchmarkingom radi u svom najčistijem obliku, ali samo za određene usluge, kao što je online streaming. Dakle, prvenstveno gledamo na metriku proizvoda specifičnu za aplikaciju.

Kao rezultat toga, prilikom skaliranja analiziramo:
- CPU i RAM indikatori,
- broj zahtjeva u redu,
- vrijeme odziva,
— prognoza zasnovana na akumuliranim istorijskim podacima.

Prilikom skaliranja usluge također je važno pratiti njene ovisnosti kako se ne bi dogodilo da skaliramo prvi servis u lancu, a oni kojima pristupa padnu pod opterećenje. Da bismo uspostavili prihvatljivo opterećenje za cijeli skup usluga, gledamo historijske podatke „najbliže“ zavisne usluge (u smislu CPU-a i RAM-a, zajedno s metrikom specifičnim za aplikaciju) i uspoređujemo ih s historijskim podacima inicijaliziranje usluge, i tako dalje duž cijelog "lanca zavisnosti"", od vrha do dna.

Servis

Nakon što se mikroservis pusti u rad, na njega možemo objesiti okidače.

Evo tipičnih situacija u kojima okidači rade.
- Otkrivene su potencijalno opasne migracije.
- Objavljena su sigurnosna ažuriranja.
- Sama usluga nije ažurirana već duže vrijeme.
- Opterećenje servisa je značajno smanjeno ili su neke od njegovih metrika proizvoda izvan norme.
— Usluga više ne ispunjava nove zahtjeve platforme.

Neki od okidača su odgovorni za stabilnost rada, neki - kao funkcija održavanja sistema - na primjer, neki servis nije raspoređen duže vrijeme i njegov osnovni imidž je prestao da prolazi sigurnosne provjere.

Dashboard

Ukratko, kontrolna ploča je kontrolna ploča cijelog našeg PaaS-a.

  • Jedinstvena informacija o usluzi, sa podacima o njenoj pokrivenosti testom, broju njenih slika, broju produkcijskih kopija, verzijama itd.
  • Alat za filtriranje podataka po uslugama i oznakama (oznake pripadnosti poslovnim jedinicama, funkcionalnost proizvoda itd.)
  • Alat za integraciju sa infrastrukturnim alatima za praćenje, evidentiranje, praćenje.
  • Jedinstvena tačka dokumentacije za usluge.
  • Jedinstveni pogled na sve događaje po službi.

Šta znamo o mikroservisima
Šta znamo o mikroservisima
Šta znamo o mikroservisima
Šta znamo o mikroservisima

Ukupno

Prije uvođenja PaaS-a, novi programer bi mogao provesti nekoliko sedmica razumijevajući sve alate potrebne za pokretanje mikroservisa u proizvodnji: Kubernetes, Helm, naše interne TeamCity funkcije, postavljanje veze s bazama podataka i keš memorija na način otporan na greške, itd. Sada je potrebno nekoliko sati da se pročita brzi početak i napravi sam servis.

Napravio sam izvještaj na ovu temu za HighLoad++ 2018, možete vidjeti видео и prezentacija.

Bonus pjesma za one koji pročitaju do kraja

Mi u Avitu organizujemo internu trodnevnu obuku za programere iz Chris Richardson, stručnjak za mikroservisnu arhitekturu. Želimo da pružimo priliku da u njoj učestvujemo jednom od čitalaca ovog posta. to je program obuke je objavljen.

Obuka će se održati od 5. do 7. avgusta u Moskvi. Ovo su radni dani koji će biti potpuno zauzeti. Ručak i trening će biti u našoj kancelariji, a odabrani učesnik sam plaća put i smještaj.

Možete se prijaviti za učešće u ovoj google formi. Od Vas - odgovor na pitanje zašto trebate pohađati obuku i informacije kako da Vas kontaktiramo. Odgovorite na engleskom, jer će učesnika koji stigne na trening izabrati sam Chris.
Ime polaznika obuke objavićemo uz ažuriranje ove objave i na društvenim mrežama Avito za programere (AvitoTech u Facebook, Вконтакте, Twitter) najkasnije do 19. jula.

izvor: www.habr.com

Dodajte komentar