Què sabem dels microserveis

Hola! Em dic Vadim Madison, dirigeixo el desenvolupament de la plataforma del sistema Avito. Com a l'empresa estem passant d'una arquitectura monolítica a un microservei s'ha dit més d'una vegada. És hora de compartir com hem transformat la nostra infraestructura per treure el màxim profit dels microserveis i no perdre'ns. Com ens ajuda PaaS aquí, com hem simplificat el desplegament i hem reduït la creació d'un microservei a un sol clic: segueix llegint. No tot el que escric a continuació està totalment implementat a Avito, part d'això és com desenvolupem la nostra plataforma.

(I al final d'aquest article, parlaré de l'oportunitat de participar en un seminari de tres dies d'un expert en arquitectura de microserveis, Chris Richardson).

Què sabem dels microserveis

Com hem arribat als microserveis

Avito és un dels anuncis classificats més grans del món, publica més de 15 milions d'anuncis nous al dia. El nostre backend accepta més de 20 mil sol·licituds per segon. Ara tenim diversos centenars de microserveis.

Fa més d'un any que hem estat construint una arquitectura de microservei. Com exactament - els nostres col·legues en detall va dir a la nostra secció a RIT++ 2017. A CodeFest 2017 (vegeu vídeo), Sergey Orlov i Mikhail Prokopchuk van explicar amb detall per què necessitàvem la transició als microserveis i quin paper va jugar Kubernetes aquí. Bé, ara estem fent tot el possible per minimitzar els costos d'escala inherents a aquesta arquitectura.

Inicialment, no vam crear un ecosistema que ens ajudés de manera integral en el desenvolupament i llançament de microserveis. Acaben de recollir solucions intel·ligents de codi obert, les van llançar a casa i van oferir al desenvolupador que les tractés. Com a resultat, va anar a una dotzena de llocs (taulers de comandament, serveis interns), després de la qual cosa va reforçar el seu desig de tallar el codi a la manera antiga, en un monòlit. El color verd dels diagrames següents indica què fa el desenvolupador d'una manera o altra amb les seves pròpies mans, el color groc indica l'automatització.

Què sabem dels microserveis

Ara, a la utilitat PaaS CLI, un equip crea un servei nou i dos més afegeixen una base de dades nova i la despleguen a Stage.

Què sabem dels microserveis

Com superar l'era de la "fragmentació dels microserveis"

Amb una arquitectura monolítica, per la coherència dels canvis en el producte, els desenvolupadors es van veure obligats a esbrinar què passava amb els seus veïns. Quan es treballa en la nova arquitectura, els contextos de servei ja no depenen els uns dels altres.

A més, perquè l'arquitectura de microservei sigui efectiva, cal establir molts processos, a saber:

• tala;
• sol·licitud de seguiment (Jaeger);
• agregació d'errors (Sentry);
• estats, missatges, esdeveniments de Kubernetes (processament de flux d'esdeveniments);
• límit de cursa / disjuntor (podeu utilitzar Hystrix);
• control de connectivitat del servei (utilitzem Netramesh);
• seguiment (Grafana);
• muntatge (TeamCity);
• comunicació i notificació (Slack, correu electrònic);
• seguiment de tasques; (Jira)
• preparació de la documentació.

Per garantir que el sistema no perdi la integritat i es mantingui eficient a mesura que s'escala, hem repensat l'organització dels microserveis a Avito.

Com gestionem els microserveis

Avito ajuda a dur a terme una "política de partit" única entre els molts microserveis:

  • divisió de la infraestructura en capes;
  • el concepte de Plataforma com a Servei (PaaS);
  • supervisant tot el que passa amb els microserveis.

Els nivells d'abstracció de la infraestructura inclouen tres capes. Anem de dalt a baix.

A. Top - malla de servei. Al principi vam provar Istio, però va resultar que utilitza massa recursos, que és massa car per als nostres volums. Per tant, l'enginyer sènior de l'equip d'arquitectura Alexander Lukyanchenko va desenvolupar la seva pròpia solució − Netramesh (disponible en codi obert), que actualment estem utilitzant en producció i que consumeix diverses vegades menys recursos que Istio (però no fa tot el que Istio pot presumir).
B. Mitjà - Kubernetes. En ell, despleguem i operem microserveis.
C. Fons - metall nu. No fem servir núvols ni coses com OpenStack, sinó que ens asseiem completament sobre metall nu.

Totes les capes es combinen amb PaaS. I aquesta plataforma, al seu torn, consta de tres parts.

I. Generadors, gestionat mitjançant la utilitat CLI. És ella qui ajuda el desenvolupador a crear un microservei de la manera correcta i amb un mínim d'esforç.

II. Col·lector consolidat amb control de tots els instruments mitjançant un quadre de comandament comú.

III. emmagatzematge. Es connecta amb programadors que configuren automàticament activadors per a accions significatives. Gràcies a aquest sistema, no es perd cap tasca només perquè algú s'ha oblidat de posar una tasca a Jira. Utilitzem una eina interna anomenada Atlas per a això.

Què sabem dels microserveis

La implementació dels microserveis a Avito també es realitza segons un esquema únic, que simplifica el control sobre ells en cada fase de desenvolupament i llançament.

Com funciona la canalització estàndard de desenvolupament de microserveis

En general, la cadena de creació de microserveis té aquest aspecte:

CLI-push → Integració contínua → Bake → Desplegar → Proves artificials → Proves Canary → Squeeze Testing → Producció → Manteniment.

Passem-ho exactament en aquest ordre.

CLI-push

• Creació d'un microservei.
Vam lluitar durant molt de temps per ensenyar a tots els desenvolupadors com fer microserveis. Inclou instruccions detallades escrites a Confluence. Però els esquemes van canviar i es van complementar. El resultat: es va formar un coll d'ampolla al començament del viatge: es va trigar molt més temps a llançar microserveis del que es permetia, i tot i així sovint hi havia problemes a l'hora de crear-los.

Al final, vam crear una senzilla utilitat CLI que automatitza els passos bàsics per crear un microservei. De fet, substitueix el primer git push. Això és exactament el que fa.

- Crea un servei segons una plantilla - pas a pas, en el mode "assistent". Disposem de plantilles per als principals llenguatges de programació del backend d'Avito: PHP, Golang i Python.

- Una comanda a la vegada desplega un entorn per al desenvolupament local en una màquina específica - Minikube augmenta, els gràfics Helm es generen automàticament i s'executen en kubernetes locals.

— Connecta la base de dades requerida. El desenvolupador no necessita saber la IP, l'inici de sessió i la contrasenya per accedir a la base de dades que necessita, almenys a nivell local, almenys a Stage, almenys en producció. A més, la base de dades es desplega immediatament en una configuració tolerant a errors i amb equilibri.

- Realitza el mateix muntatge en viu. Suposem que el desenvolupador va corregir alguna cosa al microservei mitjançant el seu IDE. La utilitat veu els canvis al sistema de fitxers i, a partir d'ells, reconstrueix l'aplicació (per Golang) i es reinicia. Per a PHP, simplement reenviem el directori dins del cub i allà la recàrrega en directe s'obté "automàticament".

- Genera autotests. En forma de espais en blanc, però força utilitzable.

• Desplega el microservei.

Solia ser una mica trist desplegar un microservei amb nosaltres. Obligatori requerit:

I. Dockerfile.

II. Config.
III. Helm-chart, que és feixuc en si mateix i inclou:

- els mateixos gràfics;
- plantilles;
- valors específics tenint en compte diferents entorns.

Hem eliminat el dolor de reelaborar els manifests de Kubernetes i ara es generen automàticament. Però el més important, vam simplificar el desplegament al límit. A partir d'ara, tenim un Dockerfile i el desenvolupador escriu tota la configuració en un únic fitxer app.toml curt.

Què sabem dels microserveis

Sí, i al mateix app.toml, ara hi ha una qüestió d'un minut. Prescriurem on quantes còpies del servei s'han de generar (al servidor de desenvolupament, a la posada en escena, a la producció), indiquen les seves dependències. Observeu la mida de la línia = "petit" al bloc [motor]. Aquest és el límit que s'assignarà al servei mitjançant Kubernetes.

A més, a partir de la configuració, es generen automàticament tots els Helm-charts necessaris i es creen connexions a les bases de dades.

• Validació bàsica. Aquests controls també estan automatitzats.
Cal fer un seguiment:
- hi ha un Dockerfile;
- hi ha app.toml;
- Hi ha documentació?
— si per ordre de dependència;
— si s'estableixen regles d'alerta.
Fins a l'últim punt: el propi propietari del servei especifica quines mètriques de producte cal controlar.

• Elaboració de documentació.
Encara és una zona problemàtica. Sembla ser el més evident, però al mateix temps el registre “sovint oblidat”, i per tant la baula vulnerable de la cadena.
Cal que la documentació sigui per a cada microservei. Inclou els següents blocs.

I. Breu descripció del servei. Només unes quantes frases sobre què fa i per a què serveix.

II. Enllaç al diagrama d'arquitectura. És important que d'un cop d'ull sigui fàcil d'entendre, per exemple, si utilitzeu Redis per a la memòria cau o com a magatzem de dades principal en mode persistent. A Avito, de moment, aquest és un enllaç a Confluence.

III. runbook. Una petita guia per posar en marxa el servei i les subtileses de la seva gestió.

IV. Preguntes freqüents, on seria bo anticipar-se als problemes que puguin trobar els seus companys a l'hora de treballar amb el servei.

V. Descripció dels punts finals de l'API. Si de sobte no heu especificat les destinacions, els companys els microserveis dels quals estan connectats al vostre gairebé segur que ho pagaran. Ara fem servir Swagger per a això i la nostra solució anomenada breu.

VI. Etiquetes. O marcadors que mostren a quin producte, funcionalitat, divisió estructural de l'empresa pertany el servei. Ajuden a entendre ràpidament, per exemple, si estàs veient la funcionalitat que els teus companys van implementar per a la mateixa unitat de negoci fa una setmana.

VII. Propietari o propietaris del servei. En la majoria dels casos, es pot determinar automàticament mitjançant PaaS, però per a l'assegurança, necessitem que el desenvolupador també les especifiqui manualment.

Finalment, és una bona pràctica realitzar revisions de documentació, de manera similar a les revisions de codi.

Integració contínua

  • Preparació de repositoris.
  • Creació d'un pipeline a TeamCity.
  • Concessió de drets.
  • Cerca propietaris de serveis. Aquí hi ha un esquema híbrid: marcatge manual i automatització mínima de PaaS. L'esquema totalment automàtic falla quan els serveis es transfereixen al suport d'un altre equip de desenvolupament o, per exemple, si el desenvolupador del servei surt.
  • Registre del servei a Atlas (Vegeu més amunt). Amb tots els seus propietaris i dependències.
  • Comprovació de migracions. Comprovem si n'hi ha de potencialment perillosos entre ells. Per exemple, en un d'ells, apareix una taula d'alteració o una altra cosa que pot trencar la compatibilitat de l'esquema de dades entre diferents versions del servei. Aleshores, la migració no es realitza, sinó que es posa en una subscripció: PaaS hauria de senyalitzar el propietari del servei quan sigui segur aplicar-lo.

Enfornar

La següent etapa és l'embalatge dels serveis abans del desplegament.

  • Muntatge de l'aplicació. Segons els clàssics, en una imatge de Docker.
  • Generació de gràfics Helm per al propi servei i recursos relacionats. Inclòs per a bases de dades i memòria cau. Es creen automàticament d'acord amb la configuració de l'app.toml que es va generar en l'etapa CLI-push.
  • Creació de tiquets per als administradors per obrir ports (quan calgui).
  • Execució de proves unitàries i càlcul de la cobertura del codi. Si la cobertura del codi està per sota del valor llindar especificat, el més probable és que el servei no anirà més enllà, fins al desplegament. Si està a punt de ser acceptable, al servei se li assignarà un coeficient "pessimitzador": aleshores, si no hi ha cap millora en l'indicador al llarg del temps, el desenvolupador rebrà una notificació que no hi ha cap progrés en termes de proves ( i cal fer-hi alguna cosa).
  • Comptabilització de les limitacions de memòria i CPU. Bàsicament, escrivim microserveis a Golang i els executem a Kubernetes. Per tant, una subtilesa associada a la característica del llenguatge Golang: de manera predeterminada, tots els nuclis de la màquina s'utilitzen a l'inici, si no configureu explícitament la variable GOMAXPROCS, i quan s'inicien diversos serveis d'aquest tipus a la mateixa màquina, comencen. competir pels recursos, interferint els uns amb els altres. Els gràfics següents mostren com canvia el temps d'execució si l'aplicació s'executa sense contenció i en mode cursa de recursos. (Les fonts dels gràfics són aquí).

Què sabem dels microserveis

Temps d'execució, menys és millor. Màxim: 643 ms, mínim: 42 ms. La foto es pot fer clic.

Què sabem dels microserveis

Temps per a la cirurgia, menys és millor. Màxim: 14091 ns, mínim: 151 ns. La foto es pot fer clic.

En l'etapa de preparació del muntatge, podeu establir aquesta variable de manera explícita o podeu utilitzar la biblioteca automaxprocs dels nois d'Uber.

Desplega

• Comprovació de convencions. Abans de començar a oferir versions de serveis als entorns previstos, heu de comprovar el següent:
- Punts finals de l'API.
— Correspondència de les respostes dels punts finals de l'API a l'esquema.
- Format de registre.
- Configuració de capçaleres per a les sol·licituds al servei (ara això ho fa netramesh)
- Configuració del marcador de propietari quan s'envien missatges al bus (bus d'esdeveniments). Això és necessari per fer un seguiment de la connectivitat dels serveis a través del bus. Podeu enviar tant dades idempotents al bus que no augmenten la connectivitat dels serveis (que és bo), com dades empresarials que milloren la connectivitat dels serveis (que és molt dolent!). I en el moment en què aquesta connectivitat es converteix en un problema, entendre qui escriu i llegeix l'autobús ajuda a separar correctament els serveis.

De moment, a Avito no hi ha gaires convencions, però la seva piscina s'està ampliant. Com més acords d'aquest tipus siguin entenedors i convenients per a l'equip, més fàcil serà mantenir la coherència entre els microserveis.

Assajos sintètics

• Proves de bucle tancat. Per a això, ara fem servir codi obert hoverfly.io. En primer lloc, registra la càrrega real del servei i després, només en un bucle tancat, l'emula.

• Proves d'estrès. Intentem portar tots els serveis a un rendiment òptim. I totes les versions de cada servei s'han de sotmetre a proves de càrrega, de manera que puguem entendre el rendiment actual del servei i la diferència amb les versions anteriors del mateix servei. Si, després d'una actualització del servei, el seu rendiment ha disminuït una vegada i mitja, aquest és un senyal clar per als seus propietaris: cal aprofundir en el codi i corregir la situació.
Partim de les dades recollides, per exemple, per tal d'implementar correctament l'escalat automàtic i, al final, per entendre en general com d'escalable és el servei.

Durant les proves de càrrega, comprovem si el consum de recursos compleix els límits establerts. I ens centrem principalment en els extrems.

a) Observem la càrrega total.
- Massa petit: el més probable és que alguna cosa no funcioni en absolut si la càrrega cau de sobte diverses vegades.
- Massa gran: cal optimització.

b) Mireu el tall RPS.
Aquí observem la diferència entre la versió actual i l'anterior i el nombre total. Per exemple, si el servei ofereix 100 rps, o bé està mal escrit o aquestes són les seves especificitats, però en qualsevol cas, aquesta és una raó per mirar el servei molt de prop.
Si, per contra, hi ha massa RPS, llavors, potser, algun tipus d'error i alguns dels punts finals van deixar d'executar la càrrega útil, però només alguns return true;

Proves canàries

Un cop superades les proves sintètiques, executem el microservei en un nombre reduït d'usuaris. Comencem amb cura, amb una petita part de l'audiència prevista del servei: menys del 0,1%. En aquesta fase, és molt important que s'introdueixin les mètriques tècniques i de producte correctes en el seguiment perquè mostrin el problema al servei el més ràpidament possible. El temps mínim de la prova canària és de 5 minuts, el principal és de 2 hores. Per a serveis complexos, establim l'hora en mode manual.
Analitzem:
- mètriques específiques de l'idioma, en particular, els treballadors php-fpm;
— errors en Sentry;
— estats de resposta;
— temps de resposta (temps de resposta), exacte i mitjà;
- latència;
- excepcions, gestionades i no gestionades;
- mètriques del producte.

Prova de compressió

Les proves de compressió també s'anomenen proves de "compressió". El nom de la tècnica es va introduir a Netflix. La seva essència és que primer omplim una instància amb trànsit real fins a l'estat de fallada i així establim el seu límit. A continuació, afegim una altra instància i carreguem aquesta parella, de nou al màxim; veiem el seu sostre i delta amb el primer cop. Així connectem una instància per pas i calculem el patró dels canvis.
Les dades de les proves mitjançant "espremer" també flueixen a una base de dades comuna de mètriques, on enriqueixem els resultats de la càrrega artificial amb elles, o fins i tot substituïm els "sintètics" per ells.

Producció

• Escalat. Desplegant el servei a la producció, controlem com s'escala. Al mateix temps, el seguiment només dels indicadors de la CPU, segons la nostra experiència, és ineficient. L'escalat automàtic amb benchmarking RPS funciona en la seva forma més pura, però només per a determinats serveis, com ara la transmissió en línia. Per tant, mirem principalment les mètriques de producte específiques de l'aplicació.

Com a resultat, en escalar, analitzem:
- Indicadors de CPU i RAM,
- el nombre de sol·licituds a la cua,
- temps de resposta,
— Previsió basada en dades històriques acumulades.

A l'hora d'escalar un servei, també és important fer un seguiment de les seves dependències perquè no passi que escalem el primer servei de la cadena, i els als quals accedeix quedin en càrrega. Per tal d'establir una càrrega acceptable per a tot el conjunt de serveis, mirem les dades històriques del servei dependent "més proper" (en termes de CPU i RAM, juntament amb mètriques específiques de l'aplicació) i les comparem amb les dades històriques de el servei d'inicialització, i així successivament al llarg de tota la "cadena de dependència", de dalt a baix.

Обслуживание

Després de posar en funcionament el microservei, podem penjar-hi els activadors.

Aquí hi ha situacions típiques en què funcionen els activadors.
- S'han detectat migracions potencialment perilloses.
- S'han publicat actualitzacions de seguretat.
- El servei en si no s'actualitza des de fa molt de temps.
— La càrrega del servei ha disminuït notablement o algunes de les mètriques del producte estan fora de la norma.
— El servei ja no compleix els nous requisits de la plataforma.

Alguns dels desencadenants són els responsables de l'estabilitat de l'obra, d'altres -com a funció de manteniment del sistema-, per exemple, algun servei fa molt de temps que no es desplega i la seva imatge base ha deixat de passar controls de seguretat.

panell

En resum, el tauler de control és el tauler de control de tot el nostre PaaS.

  • Un únic punt d'informació sobre el servei, amb dades sobre la seva cobertura de proves, el nombre de les seves imatges, el nombre de còpies de producció, versions, etc.
  • Una eina per filtrar les dades per serveis i etiquetes (proves de pertinença a unitats de negoci, funcionalitat del producte, etc.)
  • Eina d'integració amb eines d'infraestructura de traça, registre, monitorització.
  • Punt únic de documentació dels serveis.
  • Un únic punt de vista de tots els esdeveniments per servei.

Què sabem dels microserveis
Què sabem dels microserveis
Què sabem dels microserveis
Què sabem dels microserveis

En total

Abans de la introducció de PaaS, un nou desenvolupador podia passar diverses setmanes entendre totes les eines necessàries per llançar un microservei en producció: Kubernetes, Helm, les nostres funcions internes de TeamCity, establir una connexió a bases de dades i memòria cau de manera segura, etc. Ara es triguen un parell d'hores a llegir l'inici ràpid i fer el propi servei.

Vaig fer un informe sobre aquest tema per a HighLoad ++ 2018, podeu veure vídeo и presentació.

Bonus track per a aquells que llegiu fins al final

A Avito organitzem una formació interna de tres dies per a desenvolupadors de Chris Richardson, un expert en arquitectura de microserveis. Volem donar l'oportunitat de participar-hi a un dels lectors d'aquest post. Aquí s'ha publicat el programa de formació.

La formació se celebrarà del 5 al 7 d'agost a Moscou. Són dies laborables que estaran plenament ocupats. El dinar i la formació seran a la nostra oficina, i el participant escollit paga ell mateix el desplaçament i l'allotjament.

Podeu sol·licitar-hi participar en aquest formulari de google. De tu: la resposta a la pregunta per què necessites assistir a la formació i informació sobre com contactar amb tu. Resposta en anglès, perquè el participant que arribi a la formació serà escollit pel mateix Chris.
Anunciarem el nom del participant de la formació amb una actualització d'aquesta publicació i a les xarxes socials Avito per a desenvolupadors (AvitoTech en Facebook, VKontakte, Twitter) com a màxim el 19 de juliol.

Font: www.habr.com

Afegeix comentari