Hvad ved vi om mikrotjenester

Hej! Mit navn er Vadim Madison, jeg leder udviklingen af ​​Avito System Platform. Det er blevet sagt mere end én gang, hvordan vi i virksomheden bevæger os fra en monolitisk arkitektur til en mikroservices. Det er tid til at fortælle, hvordan vi har transformeret vores infrastruktur for at få mest muligt ud af mikrotjenester og forhindre os i at fare vild i dem. Hvordan PaaS hjælper os her, hvordan vi forenklede implementeringen og reducerede oprettelsen af ​​en mikroservice til et enkelt klik - læs videre. Ikke alt, hvad jeg skriver om nedenfor, er fuldt implementeret i Avito, noget af det er, hvordan vi udvikler vores platform.

(Og i slutningen af ​​denne artikel vil jeg tale om muligheden for at deltage i et tre-dages seminar fra mikroservicearkitektur-ekspert Chris Richardson).

Hvad ved vi om mikrotjenester

Hvordan vi kom til mikrotjenester

Avito er et af de største klassificerede websteder i verden; mere end 15 millioner nye annoncer offentliggøres på det om dagen. Vores backend accepterer mere end 20 tusinde anmodninger i sekundet. Vi har i øjeblikket flere hundrede mikrotjenester.

Vi har bygget en mikroservicearkitektur i flere år nu. Hvordan præcist - vores kolleger i detaljer fortalte på vores sektion på RIT++ 2017. Ved CodeFest 2017 (se. видео), Sergey Orlov og Mikhail Prokopchuk forklarede i detaljer, hvorfor vi havde brug for overgangen til mikrotjenester, og hvilken rolle Kubernetes spillede her. Nå, nu gør vi alt for at minimere de skaleringsomkostninger, der er iboende i sådan en arkitektur.

Til at begynde med skabte vi ikke et økosystem, der ville hjælpe os med at udvikle og lancere mikrotjenester. De samlede simpelthen fornuftige open source-løsninger, lancerede dem derhjemme og inviterede udvikleren til at tage sig af dem. Som et resultat gik han til et dusin steder (dashboards, interne tjenester), hvorefter han blev stærkere i sit ønske om at skære kode på den gamle måde, i en monolit. Den grønne farve i diagrammerne nedenfor indikerer, hvad udvikleren gør på den ene eller anden måde med sine egne hænder, og den gule farve indikerer automatisering.

Hvad ved vi om mikrotjenester

Nu i PaaS CLI-værktøjet oprettes en ny tjeneste med én kommando, og en ny database tilføjes med to mere og implementeres til Stage.

Hvad ved vi om mikrotjenester

Sådan overvindes æraen med "mikroservicefragmentering"

Med en monolitisk arkitektur blev udviklere af hensyn til konsistensen af ​​ændringer i produktet tvunget til at finde ud af, hvad der foregik med deres naboer. Når man arbejder med den nye arkitektur, er servicesammenhænge ikke længere afhængige af hinanden.

For at en mikroservicearkitektur skal være effektiv, skal der desuden etableres mange processer, nemlig:

• logning;
• anmode om sporing (Jaeger);
• fejlaggregering (vagt);
• statusser, meddelelser, hændelser fra Kubernetes (hændelsesstrømbehandling);
• race limit / afbryder (du kan bruge Hystrix);
• kontrol af tjenesteforbindelse (vi bruger Netramesh);
• overvågning (Grafana);
• montering (TeamCity);
• kommunikation og notifikation (Slack, e-mail);
• opgavesporing; (Jira)
• udarbejdelse af dokumentation.

For at sikre, at systemet ikke mister sin integritet og forbliver effektivt, mens det skaleres, gentænkte vi organiseringen af ​​mikrotjenester i Avito.

Sådan administrerer vi mikrotjenester

Følgende hjælper med at implementere en samlet "partipolitik" blandt mange Avito-mikrotjenester:

  • opdeling af infrastruktur i lag;
  • Platform as a Service (PaaS) koncept;
  • overvågning af alt, hvad der sker med mikrotjenester.

Infrastrukturabstraktionslag omfatter tre lag. Lad os gå fra top til bund.

A. Top - servicenet. Først prøvede vi Istio, men det viste sig, at det bruger for mange ressourcer, hvilket er for dyrt for vores mængder. Derfor udviklede senioringeniør i arkitektteamet Alexander Lukyanchenko sin egen løsning - Netramesh (tilgængelig i Open Source), som vi i øjeblikket bruger i produktionen, og som bruger flere gange færre ressourcer end Istio (men gør ikke alt, hvad Istio kan prale af).
B. Medium - Kubernetes. Vi implementerer og driver mikrotjenester på den.
C. Bund - bart metal. Vi bruger ikke skyer eller ting som OpenStack, men stoler udelukkende på bart metal.

Alle lag er kombineret af PaaS. Og denne platform består til gengæld af tre dele.

I. Generatorer, styret via et CLI-værktøj. Det er hende, der hjælper udvikleren med at skabe en mikroservice på den rigtige måde og med et minimum af indsats.

II. Konsolideret samler med kontrol over alle værktøjer gennem et fælles dashboard.

III. Opbevaring. Forbinder med planlæggere, der automatisk sætter udløsere for væsentlige handlinger. Takket være sådan et system går der ikke glip af en eneste opgave, bare fordi nogen har glemt at konfigurere en opgave i Jira. Vi bruger et internt værktøj kaldet Atlas til dette.

Hvad ved vi om mikrotjenester

Implementeringen af ​​mikrotjenester i Avito udføres også i henhold til et enkelt skema, som forenkler kontrollen over dem på hvert trin af udvikling og frigivelse.

Hvordan fungerer en standard mikroserviceudviklingspipeline?

Generelt ser mikroservice-oprettelseskæden sådan ud:

CLI-push → Kontinuerlig Integration → Bage → Deploy → Kunstige tests → Kanarie-tests → Squeeze Testing → Produktion → Vedligeholdelse.

Lad os gennemgå det præcis i denne rækkefølge.

CLI-skub

• Oprettelse af en mikrotjeneste.
Vi kæmpede i lang tid for at lære enhver udvikler, hvordan man laver mikrotjenester. Dette omfattede at skrive detaljerede instruktioner i Confluence. Men ordningerne ændrede sig og blev suppleret. Resultatet er, at der dukkede en flaskehals op i begyndelsen af ​​rejsen: det tog meget længere tid at lancere mikrotjenester, og stadig opstod der ofte problemer under deres oprettelse.

Til sidst byggede vi et simpelt CLI-værktøj, der automatiserer de grundlæggende trin, når du opretter en mikrotjeneste. Faktisk erstatter det det første git-push. Her er præcis, hvad hun gør.

— Opretter en tjeneste i henhold til en skabelon — trin for trin, i "wizard"-tilstand. Vi har skabeloner til de vigtigste programmeringssprog i Avito-backend: PHP, Golang og Python.

- Én kommando ad gangen implementerer et miljø til lokal udvikling på en bestemt maskine - Minikube lanceres, Helm-diagrammer genereres automatisk og lanceres i lokale kubernetes.

— Forbinder den nødvendige database. Udvikleren behøver ikke kende IP, login og adgangskode for at få adgang til den database, han har brug for - det være sig lokalt, på scenen eller i produktion. Desuden implementeres databasen med det samme i en fejltolerant konfiguration og med balancering.

— Den udfører selv levende montering. Lad os sige, at en udvikler rettede noget i en mikrotjeneste gennem sin IDE. Værktøjet ser ændringer i filsystemet og, baseret på dem, genopbygger programmet (for Golang) og genstarter. For PHP videresender vi simpelthen mappen inde i kuben, og der opnås live-reload "automatisk".

— Genererer autotests. I form af emner, men ganske velegnet til brug.

• Implementering af mikroservice.

At implementere en mikroservice plejede at være lidt af en opgave for os. Følgende var påkrævet:

I. Dockerfile.

II. Konfig.
III. Hjelmdiagram, som i sig selv er besværligt og inkluderer:

— selve søkortene;
— skabeloner;
— specifikke værdier, der tager hensyn til forskellige miljøer.

Vi har taget smerten ud af at omarbejde Kubernetes-manifester, så de nu genereres automatisk. Men vigtigst af alt forenklede de implementeringen til det yderste. Fra nu af har vi en Dockerfile, og udvikleren skriver hele konfigurationen i en enkelt kort app.toml-fil.

Hvad ved vi om mikrotjenester

Ja, og i selve app.toml er der ikke noget at gøre i et minut. Vi specificerer, hvor og hvor mange kopier af tjenesten, der skal rejses (på dev-serveren, på iscenesættelse, i produktion), og angiver dens afhængigheder. Bemærk linjestørrelsen = "lille" i [motor]-blokken. Dette er den grænse, der vil blive tildelt tjenesten via Kubernetes.

Derefter, baseret på konfigurationen, genereres alle de nødvendige Helm-diagrammer automatisk, og der oprettes forbindelser til databaserne.

• Grundlæggende validering. Sådanne kontroller er også automatiserede.
Skal spore:
— er der en Dockerfile;
— er der app.toml;
- Er der dokumentation tilgængelig?
— er afhængigheden i orden?
— om der er fastsat varslingsregler.
Til det sidste punkt: ejeren af ​​tjenesten bestemmer selv, hvilke produktmålinger, der skal overvåges.

• Udarbejdelse af dokumentation.
Stadig et problemområde. Det ser ud til at være det mest oplagte, men samtidig er det også en rekord "ofte glemt", og derfor et sårbart led i kæden.
Det er nødvendigt, at der er dokumentation for hver mikroservice. Det inkluderer følgende blokke.

I. Kort beskrivelse af tjenesten. Bogstaveligt talt et par sætninger om, hvad det gør, og hvorfor det er nødvendigt.

II. Link til arkitekturdiagram. Det er vigtigt, at det med et hurtigt blik er let at forstå, for eksempel om du bruger Redis til caching eller som hoveddatalager i persistent mode. I Avito for nu er dette et link til Confluence.

III. Runbook. En kort guide til at starte tjenesten og de forviklinger, der er forbundet med at håndtere den.

IV. FAQ, hvor det vil være godt at forudse de problemer, som dine kollegaer kan støde på, når de arbejder med tjenesten.

V. Beskrivelse af endepunkter for API'en. Hvis du pludselig ikke har angivet destinationerne, vil kolleger, hvis mikrotjenester er relateret til din, næsten helt sikkert betale for det. Nu bruger vi Swagger og vores løsning kaldet brief til dette.

VI. Etiketter. Eller markører, der viser, hvilket produkt, funktionalitet eller strukturel division af virksomheden, tjenesten tilhører. De hjælper dig med hurtigt at forstå, for eksempel om du skærer i funktionalitet, som dine kolleger rullede ud for den samme forretningsenhed for en uge siden.

VII. Ejer eller ejere af tjenesten. I de fleste tilfælde kan det - eller dem - bestemmes automatisk ved hjælp af PaaS, men for at være på den sikre side kræver vi, at udvikleren angiver dem manuelt.

Endelig er det en god praksis at gennemgå dokumentation, svarende til kodegennemgang.

Kontinuerlig integration

  • Forberedelse af repositories.
  • Oprettelse af en pipeline i TeamCity.
  • Indstillingsrettigheder.
  • Søg efter tjenesteejere. Her er en hybridordning - manuel mærkning og minimal automatisering fra PaaS. En fuldautomatisk ordning fejler, når tjenester overføres til support til et andet udviklingsteam, eller for eksempel hvis tjenesteudvikleren stopper.
  • Registrering af en tjeneste i Atlas (se ovenfor). Med alle dets ejere og afhængigheder.
  • Kontrol af migrationer. Vi tjekker, om nogen af ​​dem er potentielt farlige. For eksempel dukker der i en af ​​dem en ændringstabel eller noget andet op, der kan bryde kompatibiliteten af ​​dataskemaet mellem forskellige versioner af tjenesten. Så udføres migreringen ikke, men placeres i et abonnement - PaaS'en skal signalere tjenesteejeren, hvornår det er sikkert at bruge det.

Bage

Næste trin er pakketjenester før implementering.

  • Opbygning af applikationen. Ifølge klassikerne - i et Docker-billede.
  • Generering af Helm-diagrammer for selve tjenesten og relaterede ressourcer. Herunder til databaser og cache. De oprettes automatisk i overensstemmelse med app.toml-konfigurationen, der blev genereret på CLI-push-stadiet.
  • Oprettelse af billetter til administratorer til åbne porte (når det er nødvendigt).
  • Kørsel af enhedstest og beregning af kodedækning. Hvis kodedækningen er under den angivne tærskel, vil tjenesten højst sandsynligt ikke gå videre - til implementering. Hvis det er på grænsen til acceptabelt, vil tjenesten blive tildelt en "pessimerende" koefficient: så, hvis der ikke er nogen forbedring i indikatoren over tid, vil udvikleren modtage en meddelelse om, at der ikke er nogen fremskridt med hensyn til test ( og der skal gøres noget ved det).
  • Tager højde for hukommelses- og CPU-begrænsninger. Vi skriver primært mikrotjenester i Golang og kører dem i Kubernetes. Derfor en subtilitet forbundet med det særlige ved Golang-sproget: som standard, når du starter, bruges alle kerner på maskinen, hvis du ikke udtrykkeligt indstiller GOMAXPROCS-variablen, og når flere sådanne tjenester startes på samme maskine, begynder de at konkurrere om ressourcer og forstyrre hinanden. Graferne nedenfor viser, hvordan eksekveringstiden ændres, hvis du kører applikationen uden strid og i kapløbet om ressourcer-tilstand. (Kilder til grafer er her).

Hvad ved vi om mikrotjenester

Udførelsestid, mindre er bedre. Maksimum: 643 ms, minimum: 42 ms. Billedet er klikbart.

Hvad ved vi om mikrotjenester

Tid til operation, mindre er bedre. Maksimum: 14091 ns, minimum: 151 ns. Billedet er klikbart.

På monteringsforberedelsesstadiet kan du indstille denne variabel eksplicit, eller du kan bruge biblioteket automaxprocs fra fyrene fra Uber.

Indsætte

• Kontrol af konventioner. Før du begynder at levere servicesamlinger til dine tilsigtede miljøer, skal du kontrollere følgende:
- API-endepunkter.
— Overholdelse af API-endepunkters svar med skemaet.
— Logformat.
— Indstilling af overskrifter for anmodninger til tjenesten (i øjeblikket udføres dette af netramesh)
— Indstilling af ejertoken, når der sendes beskeder til begivenhedsbussen. Dette er nødvendigt for at spore forbindelsen mellem tjenester på tværs af bussen. Du kan sende både idempotente data til bussen, hvilket ikke øger forbindelsen af ​​tjenester (hvilket er godt), og forretningsdata, der styrker forbindelsen af ​​tjenester (hvilket er meget dårligt!). Og på det tidspunkt, hvor denne forbindelse bliver et problem, hjælper forståelsen af, hvem der skriver og læser bussen, med at adskille tjenesterne korrekt.

Der er ikke ret mange stævner i Avito endnu, men deres pool udvides. Jo flere sådanne aftaler er tilgængelige i en form, som teamet kan forstå og forstå, jo lettere er det at opretholde sammenhæng mellem mikrotjenester.

Syntetiske tests

• Lukket sløjfetest. Til dette bruger vi nu open source Hoverfly.io. Først registrerer den den reelle belastning på tjenesten, derefter - bare i et lukket kredsløb - emulerer den den.

• Stresstest. Vi forsøger at bringe alle tjenester til optimal ydeevne. Og alle versioner af hver tjeneste skal være genstand for belastningstest - på denne måde kan vi forstå den aktuelle ydeevne af tjenesten og forskellen med tidligere versioner af den samme tjeneste. Hvis dens ydeevne efter en serviceopdatering faldt med halvanden gang, er dette et klart signal til dets ejere: du skal grave i koden og rette situationen.
Vi bruger for eksempel de indsamlede data til at implementere automatisk skalering korrekt og i sidste ende forstår vi generelt, hvor skalerbar tjenesten er.

Ved belastningstest tjekker vi om ressourceforbruget lever op til de fastsatte grænser. Og vi fokuserer primært på ekstremer.

a) Vi ser på den samlede belastning.
- For lille - højst sandsynligt virker noget slet ikke, hvis belastningen pludselig falder flere gange.
- For stor - optimering påkrævet.

b) Vi ser på cutoff ifølge RPS.
Her ser vi på forskellen mellem den nuværende version og den forrige og den samlede mængde. For eksempel, hvis en service producerer 100 rps, så er den enten dårligt skrevet, eller også er dette dens specificitet, men under alle omstændigheder er dette en grund til at se på servicen meget nøje.
Hvis der tværtimod er for mange RPS, så er der måske en slags fejl, og nogle af endepunkterne er holdt op med at eksekvere nyttelasten, og en anden bliver simpelthen udløst return true;

Kanariske test

Efter at vi har bestået de syntetiske test, tester vi mikrotjenesten på et lille antal brugere. Vi starter forsigtigt med en lille andel af tjenestens tiltænkte målgruppe - mindre end 0,1 %. På dette tidspunkt er det meget vigtigt, at de korrekte tekniske og produktmæssige målinger indgår i overvågningen, så de hurtigst muligt viser problemet i tjenesten. Minimumstiden for en kanarietest er 5 minutter, den vigtigste er 2 timer. For komplekse tjenester indstiller vi tiden manuelt.
Lad os analysere:
— sprogspecifikke målinger, især php-fpm-arbejdere;
— fejl i Sentry;
— svarstatusser;
— responstid, nøjagtig og gennemsnitlig;
- reaktionstid;
— undtagelser, behandlede og ubehandlede;
— produktmålinger.

Squeeze test

Squeeze-test kaldes også "squeeze"-test. Navnet på teknikken blev introduceret i Netflix. Dens essens er, at vi først fylder en forekomst med reel trafik til det punkt, hvor den fejler, og dermed sætter dens grænse. Så tilføjer vi endnu en instans og indlæser dette par - igen til det maksimale; vi ser deres loft og delta med det første "squeeze". Så vi forbinder en instans ad gangen og beregner mønsteret af ændringer.
Testdata gennem "squeezing" flyder også ind i en fælles metrics-database, hvor vi enten beriger de kunstige belastningsresultater med dem, eller endda erstatter "synthetics" med dem.

Produktion

• Skalering. Når vi udruller en service til produktionen, overvåger vi, hvordan den skalerer. Vores erfaring er, at kun overvågning af CPU-indikatorer er ineffektiv. Automatisk skalering med RPS-benchmarking i sin rene form fungerer, men kun for visse tjenester, såsom online streaming. Så vi ser først på applikationsspecifikke produktmålinger.

Som et resultat analyserer vi ved skalering:
- CPU og RAM indikatorer,
— antallet af anmodninger i køen
- responstid,
— prognose baseret på akkumulerede historiske data.

Når du skalerer en tjeneste, er det også vigtigt at overvåge dens afhængigheder, så vi ikke skalerer den første tjeneste i kæden, og dem, den får adgang til, fejler under belastning. For at etablere en acceptabel belastning for hele puljen af ​​tjenester ser vi på de historiske data for den "nærmeste" afhængige tjeneste (baseret på en kombination af CPU- og RAM-indikatorer, kombineret med app-specifikke metrikker) og sammenligner dem med de historiske data af initialiseringstjenesten og så videre i hele "afhængighedskæden" ", fra top til bund.

service

Efter at mikrotjenesten er sat i drift, kan vi knytte triggere til den.

Her er typiske situationer, hvor triggere opstår.
— Potentielt farlige migrationer opdaget.
— Sikkerhedsopdateringer er blevet frigivet.
— Selve tjenesten er ikke blevet opdateret i lang tid.
— Belastningen på tjenesten er mærkbart faldet, eller nogle af dens produktmålinger er uden for det normale interval.
— Tjenesten opfylder ikke længere de nye platformskrav.

Nogle af triggerne er ansvarlige for driftsstabilitet, nogle - som en funktion af systemvedligeholdelse - for eksempel har en eller anden tjeneste ikke været installeret i lang tid, og dens basisbillede er holdt op med at bestå sikkerhedstjek.

Dashboard

Kort sagt er dashboardet kontrolpanelet for hele vores PaaS.

  • Et enkelt informationspunkt om tjenesten med data om dens testdækning, antallet af dens billeder, antallet af produktionseksemplarer, versioner osv.
  • Et værktøj til at filtrere data efter tjenester og etiketter (markører for tilhørsforhold til forretningsenheder, produktfunktionalitet osv.)
  • Et værktøj til integration med infrastrukturværktøjer til sporing, logning og overvågning.
  • Dokumentation for et enkelt servicepunkt.
  • Et enkelt synspunkt på alle begivenheder på tværs af tjenester.

Hvad ved vi om mikrotjenester
Hvad ved vi om mikrotjenester
Hvad ved vi om mikrotjenester
Hvad ved vi om mikrotjenester

I alt

Før en ny udvikler introducerer PaaS, kunne en ny udvikler bruge flere uger på at forstå alle de værktøjer, der er nødvendige for at lancere en mikroservice i produktionen: Kubernetes, Helm, vores interne TeamCity-funktioner, opsætning af forbindelser til databaser og caches på en fejltolerant måde, osv. Nu er det tager et par timer at læse hurtigstarten og oprette selve tjenesten.

Jeg gav en rapport om dette emne til HighLoad++ 2018, du kan se den видео и præsentation.

Bonustrack for dem, der læser til ende

Vi hos Avito arrangerer en intern tre-dages uddannelse for udviklere fra Chris Richardson, en ekspert i mikroservicearkitektur. Vi vil gerne give mulighed for at deltage i det til en af ​​læserne af dette indlæg. Her Træningsprogrammet er lagt ud.

Træningen finder sted fra 5. til 7. august i Moskva. Det er arbejdsdage, der vil være fuldt optaget. Frokost og træning vil være på vores kontor, og den udvalgte deltager betaler selv rejse og ophold.

Du kan søge om deltagelse i denne google-formular. Fra dig - svaret på spørgsmålet om, hvorfor du skal deltage i uddannelsen og information om, hvordan du kontakter dig. Svar på engelsk, for Chris vælger selv den deltager, der skal deltage i træningen.
Vi vil annoncere navnet på træningsdeltageren i en opdatering til dette indlæg og på sociale netværk Avito for udviklere (AvitoTech i Facebook, VKontakte, Twitter) senest den 19. juli.

Kilde: www.habr.com

Tilføj en kommentar