Sådan skalerer du fra 1 til 100 brugere

Mange startups har været igennem dette: Masser af nye brugere registrerer sig hver dag, og udviklingsteamet kæmper for at holde tjenesten kørende.

Det er et godt problem at have, men der er få klar information på nettet om, hvordan man omhyggeligt skalerer en webapplikation fra ingenting til hundredtusindvis af brugere. Typisk er der enten brandløsninger eller flaskehalsløsninger (og ofte begge dele). Derfor bruger folk ret klicherede teknikker til at skalere deres amatørprojekt til noget virkelig seriøst.

Lad os prøve at filtrere oplysningerne og skrive den grundlæggende formel ned. Vi vil skalere vores nye fotodelingsside Graminsta trin for trin fra 1 til 100 brugere.

Lad os skrive ned, hvilke konkrete handlinger der skal tages, når publikum stiger til 10, 100, 1000, 10 og 000 personer.

1 bruger: 1 maskine

Næsten hver applikation, hvad enten det er et websted eller en mobilapplikation, har tre nøglekomponenter:

  • API
  • database
  • klient (selve mobilapplikationen eller webstedet)

Databasen gemmer vedvarende data. API'en leverer anmodninger til og omkring disse data. Klienten overfører data til brugeren.

Jeg kom til den konklusion, at det er meget nemmere at tale om at skalere en applikation, hvis klienten og API-entiteterne fra et arkitektonisk synspunkt er fuldstændig adskilt.

Når vi først begynder at bygge en applikation, kan alle tre komponenter køres på den samme server. På nogle måder ligner dette vores udviklingsmiljø: en ingeniør kører databasen, API'en og klienten på den samme maskine.

I teorien kunne vi implementere det i skyen på en enkelt DigitalOcean Droplet- eller AWS EC2-instans, som vist nedenfor:
Sådan skalerer du fra 1 til 100 brugere
Med det sagt, hvis der vil være mere end én bruger på et websted, giver det næsten altid mening at dedikere et databaselag.

10 brugere: flytning af databasen til et separat niveau

At opdele databasen i administrerede tjenester som Amazon RDS eller Digital Ocean Managed Database vil tjene os godt i lang tid. Det er lidt dyrere end selvhosting på en enkelt maskine eller EC2-instans, men med disse tjenester får du en masse nyttige udvidelser ud af boksen, som vil være nyttige i fremtiden: backup af flere regioner, læsereplikaer, automatisk sikkerhedskopier og mere.

Sådan ser systemet ud nu:
Sådan skalerer du fra 1 til 100 brugere

100 brugere: flytning af klienten til et separat niveau

Heldigvis kunne vores første brugere virkelig godt lide vores applikation. Trafikken bliver mere stabil, så det er tid til at flytte klienten til et separat niveau. Det skal bemærkes, at adskillelse enheder er et nøgleaspekt ved at bygge en skalerbar applikation. Da en del af systemet modtager mere trafik, kan vi opdele det for at kontrollere, hvordan tjenesten skaleres baseret på specifikke trafikmønstre.

Det er derfor, jeg kan lide at tænke på klienten som adskilt fra API'en. Dette gør det meget nemt at tænke på at udvikle til flere platforme: web, mobilweb, iOS, Android, desktop-applikationer, tredjepartstjenester osv. De er alle kun klienter, der bruger den samme API.

For eksempel beder vores brugere nu oftest om at frigive en mobilapplikation. Hvis du adskiller klient- og API-entiteterne, bliver dette nemmere.

Sådan ser sådan et system ud:

Sådan skalerer du fra 1 til 100 brugere

1000 brugere: Tilføj load balancer

Tingene ser op. Graminsta-brugere uploader flere og flere billeder. Antallet af tilmeldinger vokser også. Vores enlige API-server har svært ved at følge med i al trafikken. Har brug for mere jern!

Load balancer er et meget kraftfuldt koncept. Nøgleidéen er, at vi sætter en load balancer foran API'et, og den distribuerer trafik til individuelle serviceinstanser. Det er sådan, vi skalerer horisontalt, hvilket betyder, at vi tilføjer flere servere med den samme kode, hvilket øger antallet af anmodninger, vi kan behandle.

Vi vil placere separate load balancere foran webklienten og foran API'en. Dette betyder, at du kan køre flere forekomster, der kører API-kode og webklientkode. Belastningsbalanceren sender anmodninger til den server, der er mindre belastet.

Her får vi en anden vigtig fordel - redundans. Når en forekomst fejler (måske overbelastet eller nedbrudt), står vi tilbage med andre, der fortsætter med at svare på indgående anmodninger. Hvis der kun var én instans, der virkede, ville hele systemet gå ned i tilfælde af fejl.

Loadbalanceren giver også automatisk skalering. Vi kan konfigurere det til at øge antallet af forekomster før spidsbelastning og reducere det, når alle brugere sover.

Med en load balancer kan API-niveauet skaleres næsten i det uendelige ved blot at tilføje nye forekomster, efterhånden som antallet af anmodninger stiger.

Sådan skalerer du fra 1 til 100 brugere

Bemærk. Lige nu er vores system meget lig det, som PaaS-virksomheder som Heroku eller Elastic Beanstalk på AWS tilbyder ud af kassen (hvilket er grunden til, at de er så populære). Heroku sætter databasen på en separat vært, administrerer en auto-scaling load balancer og giver dig mulighed for at hoste webklienten separat fra API'et. Dette er en god grund til at bruge Heroku til tidlige projekter eller startups - du får alle de grundlæggende tjenester ud af boksen.

10 brugere: CDN

Måske skulle vi have gjort det fra begyndelsen. Behandling af anmodninger og accept af nye billeder begynder at belaste vores servere for meget.

På dette stadie skal du bruge en cloud-tjeneste til lagring af statisk indhold - billeder, videoer og meget mere (AWS S3 eller Digital Ocean Spaces). Generelt bør vores API undgå at håndtere ting som at vise billeder og uploade billeder til serveren.

En anden fordel ved cloud-hosting er CDN (AWS kalder denne tilføjelse Cloudfront, men mange cloud-lagringsudbydere tilbyder det ud af boksen). CDN gemmer automatisk vores billeder i forskellige datacentre rundt om i verden.

Selvom vores primære datacenter kan være placeret i Ohio, hvis nogen anmoder om et billede fra Japan, vil cloud-udbyderen lave en kopi og gemme det i deres japanske datacenter. Den næste person, der anmoder om dette billede i Japan, vil modtage det meget hurtigere. Dette er vigtigt, når vi arbejder med store filer, såsom billeder eller videoer, der tager lang tid at downloade og overføre på tværs af planeten.

Sådan skalerer du fra 1 til 100 brugere

100 brugere: skalering af datalaget

CDN har hjulpet meget: Trafikken vokser med fuld hastighed. Den berømte videoblogger Mavid Mobrick har lige registreret sig hos os og postet sin "historie", som man siger. Takket være load balanceren holdes CPU- og hukommelsesforbruget på API-serverne lavt (ti API-forekomster kører), men vi begynder at få mange timeouts på anmodninger... hvor kommer disse forsinkelser fra?

Graver vi lidt ned i metrikken, ser vi, at CPU'en på databaseserveren er 80-90% belastet. Vi er ved grænsen.

Skalering af datalaget er nok den sværeste del af ligningen. API-servere betjener statsløse anmodninger, så vi tilføjer blot flere API-instanser. Næse flertallet databaser kan ikke gøre dette. Vi vil tale om populære relationelle databasestyringssystemer (PostgreSQL, MySQL osv.).

caching

En af de nemmeste måder at øge ydeevnen af ​​vores database på er at introducere en ny komponent: cachelaget. Den mest almindelige cachingmetode er et lager med nøgleværdier i hukommelsen, såsom Redis eller Memcached. De fleste skyer har en administreret version af disse tjenester: Elasticache på AWS og Memorystore på Google Cloud.

En cache er nyttig, når en tjeneste foretager mange gentagne opkald til databasen for at hente den samme information. Grundlæggende får vi kun adgang til databasen én gang, gemmer oplysningerne i cachen og rører dem ikke igen.

For eksempel, i vores Graminsta-tjeneste, hver gang nogen går til profilsiden for stjernen Mobrik, spørger API-serveren databasen efter oplysninger fra hans profil. Dette sker igen og igen. Da Mobriks profiloplysninger ikke ændres ved hver anmodning, er den fremragende til caching.

Vi cachelagrer resultaterne fra databasen i Redis efter nøgle user:id med en gyldighedsperiode på 30 sekunder. Nu, når nogen går ind på Mobriks profil, tjekker vi først Redis, og hvis dataene er der, overfører vi dem blot direkte fra Redis. Nu indlæser anmodninger til den mest populære profil på webstedet praktisk talt ikke vores database.

En anden fordel ved de fleste cachingtjenester er, at de er nemmere at skalere end databaseservere. Redis har en indbygget Redis Cluster-tilstand. Svarende til en load balancer1, giver det dig mulighed for at distribuere din Redis-cache på tværs af flere maskiner (på tværs af tusindvis af servere, hvis det er nødvendigt).

Næsten alle store applikationer bruger caching; det er en absolut integreret del af en hurtig API. Hurtigere forespørgselsbehandling og mere produktiv kode er alle vigtige, men uden en cache er det næsten umuligt at skalere en tjeneste til millioner af brugere.

Læs replikaer

Når antallet af forespørgsler til databasen er steget meget, er en ting mere, vi kan gøre, at tilføje læste replikaer i databasestyringssystemet. Med de administrerede tjenester beskrevet ovenfor kan dette gøres med et enkelt klik. Den læste replika forbliver aktuel i hoveddatabasen og er tilgængelig for SELECT-sætninger.

Her er vores system nu:

Sådan skalerer du fra 1 til 100 brugere

Næste trin

Da applikationen fortsætter med at skalere, vil vi fortsætte med at adskille tjenesterne for at skalere dem uafhængigt. For eksempel, hvis vi begynder at bruge Websockets, så giver det mening at trække Websockets-behandlingskoden ind i en separat tjeneste. Vi kan placere det på nye instanser bag vores egen load balancer, som kan skalere op og ned baseret på åbne Websockets-forbindelser og uanset antallet af HTTP-anmodninger.

Vi vil også fortsætte med at bekæmpe restriktioner på databaseniveau. Det er på dette stadium, at det er tid til at studere databasepartitionering og -sharding. Begge tilgange kræver ekstra overhead, men giver dig mulighed for at skalere databasen næsten på ubestemt tid.

Vi ønsker også at installere en overvågnings- og analysetjeneste som New Relic eller Datadog. Dette vil hjælpe dig med at identificere langsomme forespørgsler og forstå, hvor der er behov for forbedringer. Efterhånden som vi skalerer, ønsker vi at fokusere på at finde flaskehalse og eliminere dem – ofte ved at bruge nogle af ideerne fra tidligere afsnit.

kilder

Dette indlæg er inspireret af en af mine yndlingsindlæg om høj skalerbarhed. Jeg ønskede at gøre artiklen lidt mere specifik for de indledende faser af projekter og løsne den fra én leverandør. Sørg for at læse, hvis du er interesseret i dette emne.

Fodnoter

  1. Selvom ens med hensyn til belastningsfordeling på tværs af flere instanser, er den underliggende implementering af en Redis-klynge meget forskellig fra en belastningsbalancer. [Vend tilbage]

Sådan skalerer du fra 1 til 100 brugere

Kilde: www.habr.com

Tilføj en kommentar