brugerhandlingstjeneste: fra monolit til sky

(Souhaib Guitouni) (23. juni 2020)

Introduktion

Historisk set var BlaBlaCars backend en stor PHP-monolit. Det tillod os at gentage og opbygge funktioner hurtigt, men i det lange løb var det ikke let at opfange, vedligeholde og udvikle sig. I de sidste par år har vi nedbrudt denne gamle monolit og bevæget os mod en serviceorienteret arkitektur.

Denne artikel er en af ​​historierne om, hvordan vi styrer denne overgang med nogle detaljer om værktøjer, der hjalp os undervejs. Det vil dække de tekniske stakvalg, den generelle arkitektur og feedback på de værktøjer, vi brugte.

I – Hvorfor

Når BlaBlaCars aktivitet udvides, bliver en monolitisk arkitektur mere og mere begrænsende, hovedsagelig fordi:

  • Mens de lever, falder monolit i kobling;
  • At have teams, der arbejder på separate efterslæb, er svært at organisere på den samme kodebase;
  • Monolitter er svære at anholde for nybegyndere;
  • For alt det ovenstående bliver enhver ny funktionalitet ekstremt dyr.

Dette er grunden til, at vi i de sidste par år har redesignet vores platform til en SOA-arkitektur, på udkig efter:

  • Servere med funktionelt omfang: en tjeneste administrerer en enkelt funktionalitet og er fuldt ansvarlig for, hvordan den implementerer den.
  • Løst koblede tjenester, der kan udvikle sig uafhængigt. Teams kan arbejde og implementere i deres eget tempo.
  • Mere kodeejerskab, så tjenester har et defineret og mere reduceret omfang, så teams kan vedligeholde og betjene dem lettere.

II – Omfang og historie for brugerhandlinger

Den seneste linje, der blev lavet til en uafhængig tjeneste, var brugerhandlingerne. De hjælper vores Community Relations Team med at diagnosticere og løse brugernes problemer, som f.eks. At give refusion og opdage uregelmæssigheder eller spore svigagtig adfærd.

Mængden af ​​brugerhandlinger, som du måske forventer, er kolossal. Historisk set som en SQL-tabel havde denne del af koden præstationsproblemer. Vi fandt løsninger hver gang, men med vores udvidelse blev problemer større og større:

  • En første løsning var at oprette indekser for at gøre forespørgsler hurtigere;
  • En anden var at splitte databasen i flere tabeller.

Disse løsninger nåede stadig deres grænse, og med tiden begyndte vi at få ydeevneproblemer.

III – Datalagring

1 – Vejen til NoSQL

Valget af datalager var hovedsageligt baseret på teknisk krav:

  • Der er enorme mængder data
  • Stor mængde indsatser
  • Flere læsninger pr. sekund med behov for nye data og ydeevne
  • Mulighed for at filtrere inden for en rimelig tid

Vi ledte naturligvis efter en NoSQL-database, da distributionen gjorde det muligt for os at gemme og manipulere store mængder data og skala, når nødvendigt.

2 – Administreret tjeneste

Vi ville også gå med en administreret service for at reducere omkostningerne til vedligeholdelse. Distribuerede databaser som Hbase og Cassandra er berømt kendt for de vanskeligheder, de skaffer til databasestyringsholdene. Endnu vigtigere, for applikationsudviklingsteamet, ønskede vi at fokusere på at producere logikken i håndtering af brugerhandlinger i stedet for at bruge vores tid på at løse problemer med databaseinfrastrukturen. Det var også muligheden for at teste et nyt produkt, da anvendelsesområdet ikke er for bredt. Vi ville give noget nyt et skud!

3 – Endeligt valg

Valget landede på Bigtable af følgende grunde:

  • Volumen: Det var designet til at håndtere store mængder data, i modsætning til de fleste SQL-databaser, kan en instans håndtere 10.000 indsatser pr. Sekund, så vi valgte den minimale konfiguration med kun tre noder.
  • Skalerbarhed: Den er skalerbar og nem at replikere, du kan også administrere dataversioner.
  • Managementomkostninger: Det er en administreret tjeneste.
  • Ydeevne: Det er en GCP-tjeneste, der giver os mulighed for at have fremragende ydeevne, da det vil være i samme infrastruktur som den tjeneste, der er implementeret i GKE.

III – Hop fra et tog i bevægelse til et andet

Det svære ved at flytte fra en monolit til en tjeneste er at levere kontinuitet i tjenesten fra et eksternt synspunkt og at have intet datatab.

For at levere dette besluttede vi at køre den nye tjeneste, holde det gamle system i funktion og skrive de nye handlinger via REST i dem begge. Det næste trin vil være at flytte de historiske data fra monolitten til den nye tjeneste. Denne handling kan skabe dobbelt, så den indledende dataindlæsning skal håndtere deduplicering. Et tredje trin vil være at læse fra den nye tjeneste i stedet for det gamle system. Et sidste trin ville være at lukke den monolitiske del og den ældre SQL-database, når alt fungerer i tjenesten.

IV – Flytning af data

1 – Fra MySQL til Bigtable

Nu da vi besluttede, hvad vores måldatalager vil være, og hvordan det skal implementeres, begyndte vi at tænke på måderne til at flytte data fra monolit til den nye database. En sådan operation er kritisk, og migreringsjobben skal være:

  • Enkel og nem at udvikle: kompleksiteten i databasestikkene
  • Højtydende: da den vil læse enormt datamængder, vi vil have resultatet så hurtigt som muligt
  • Pålideligt: ​​vi ønskede intet datatab
  • Let at genstarte: hvis ting går galt, ville vi have noget, vi kunne genstart simpelthen uden mange manuelle handlinger med shell-scripts overalt og en kompleks procedure
  • Tillader transformationer: vi havde brug for at forbinde data fra flere MySQL-databaser og -tabeller for at få de endelige Bigtable-dem, dette kunne være svært, hvis manuelt scriptet.

2 – Apache Beam og Dataforløb

Vi valgte at bruge Dataflow, en distribueret administreret tjeneste leveret af Google Cloud, der giver folk mulighed for at flytte data i batch og i streamingtilstande.

Apache Beam er derimod en ramme, der bruges til at kode distribuerede scripts . Du kan derefter køre det på mange distribuerede motorer som Dataflow, Spark, Flink … Med andre ord er det et abstraktionslag til at definere dine transformationer, der kan forstås af flere motorer.

En anden cool ting ved Apache Beam er at den har out of the box-stik til flere datakilder, blandt dem både MySQL og Bigtable. Så vi oprettede datatransformationerne ved at læse fra Mysql ældre tabeller, sammenføje dem og placere resultatet i Bigtable.

2 – Hvordan gik det?

Vi foretog et par observationer, mens vi kørte migreringen:

  • Det var en udmattende opgave for MySQL: at undgå præstationsproblemer, du skal på ingen måde undgå at køre den på en kritisk database. For at undgå dette problem kørte vi det på en replika-database lavet til sådanne opgaver. Vi fulgte udførelsen på vores overvågningstjeneste (Prometheus / Grafana), der viste, at parallelle Dataflow-maskiner udmasser MySQL.
  • Det var heller ikke let for Bigtable: vi havde en lille forekomst af 3 maskiner, der kunne give 30.000 indsatser pr. sekund. Hvis du kører flere Dataflow-job, går du meget ud over det. Så tænk klogt over, hvor mange maskiner du vil have parallelt, fordi det at have det maksimale antal får dig til at tabe penge.
  • MySQL Beam-stik streamer ikke data: MySQL-stik udfører en SQL-sætning og venter for at indlæse hele svaret for at fortsætte. Dette giver dig problemer med RAM, hvis du indlæser en masse data. Så du er nødt til at teste og definere rækkevidde af brugere for at undgå at ende med en hukommelsesundtagelse.

V – Backend-tjenesten

Flere arkitektoniske mønstre var mulige, vi ville gå med en arkitektur, der kan udvikle sig i fremtiden, og som vi kan bygge trin for trin med live trafik fra første trin.

Vi besluttede at oprette en service med Spring WebFlux, den reaktive ramme at have ikke-blokerende anmodninger og derefter bedre ydeevne med funktionelle slutpunkter. Vi brugte Reactor til den bedste integration med Spring.

1 – Integrationstest med Bigtable

Integrationstest kalder APIen med flere nyttelast / headere og kontrollerer, om svaret er som forventet. For at gøre dette havde vi brug for en Bigtable-forekomst bag vores service, da vi ønskede test i det virkelige liv.

Denne forekomst skal renses ved hver kørsel for at starte fra den samme tilstand hver gang.

Løsningen var at bruge Bigtable-emulatoren til stede i Bigtable client SDK. SDK er meget rig og har flere funktioner som admin management og overvågning.

2 – Implementering og infrastruktur

Vores GCP-infrastruktur er oven på Google Kubernetes og Istio. Vi klarer det hele med Helm og Flux. Andre artikler kommer på vores blog for at gå ind i flere detaljer om vores infrastruktur!

Selvfølgelig havde vores service klassiske overvågnings-, loggnings- og advarselsender, uden dem ville vi ikke kunne køre den live , baseret på Prometheus / Grafana og ELK.

Afsluttende tanker

For at styre de store datamængder gik vi til Bigtable takket være dets evne til at skalere.Vi havde flere udfordringer som at definere dataskemaet med Bigtable-tastemønster, flytte store mængder data fra en SQL på en lokal database til en administreret NoSQL, teste og overvåge det hele.

Først implementerede vi tjenesten på vores lokale datacenter, og ved at flytte til GCP delte vi latenstiden med tre. Vores Community Relations Teams har nu hurtigere svartider og er begejstrede.