Hur man skalar från 1 till 100 000 användare

Många startups har gått igenom detta: mängder av nya användare registrerar sig varje dag, och utvecklingsteamet kämpar för att hålla tjänsten igång.

Det är ett trevligt problem att ha, men det finns lite tydlig information på webben om hur man försiktigt skalar en webbapplikation från ingenting till hundratusentals användare. Vanligtvis finns det antingen brandlösningar eller flaskhalslösningar (och ofta båda). Därför använder människor ganska klyschiga tekniker för att skala sitt amatörprojekt till något riktigt seriöst.

Låt oss försöka filtrera informationen och skriva ner den grundläggande formeln. Vi ska skala vår nya fotodelningssajt Graminsta steg för steg från 1 till 100 000 användare.

Låt oss skriva ner vilka specifika åtgärder som måste vidtas när publiken ökar till 10, 100, 1000, 10 000 och 100 000 personer.

1 användare: 1 maskin

Nästan varje applikation, oavsett om det är en webbplats eller en mobilapplikation, har tre nyckelkomponenter:

  • API
  • databas
  • klient (mobilapplikationen själv eller webbplatsen)

Databasen lagrar beständiga data. API:et skickar förfrågningar till och kring dessa data. Klienten överför data till användaren.

Jag kom fram till att det är mycket lättare att prata om att skala en applikation om klienten och API-entiteterna ur arkitektonisk synvinkel är helt åtskilda.

När vi först börjar bygga en applikation kan alla tre komponenterna köras på samma server. På vissa sätt liknar detta vår utvecklingsmiljö: en ingenjör kör databasen, API:et och klienten på samma maskin.

I teorin skulle vi kunna distribuera det i molnet på en enda DigitalOcean Droplet eller AWS EC2-instans, som visas nedan:
Hur man skalar från 1 till 100 000 användare
Med det sagt, om det kommer att finnas mer än en användare på en webbplats, är det nästan alltid vettigt att dedikera ett databaslager.

10 användare: flytta databasen till en separat nivå

Att dela upp databasen i hanterade tjänster som Amazon RDS eller Digital Ocean Managed Database kommer att tjäna oss väl under lång tid. Det är lite dyrare än självhosting på en enda maskin eller EC2-instans, men med dessa tjänster får du många användbara tillägg ur lådan som kommer väl till pass i framtiden: säkerhetskopiering av flera regioner, läsrepliker, automatisk säkerhetskopior och mer.

Så här ser systemet ut nu:
Hur man skalar från 1 till 100 000 användare

100 användare: flytta klienten till en separat nivå

Lyckligtvis gillade våra första användare verkligen vår applikation. Trafiken blir mer stabil, så det är dags att flytta klienten till en separat nivå. Det bör nämnas att separation enheter är en nyckelaspekt för att bygga en skalbar applikation. Eftersom en del av systemet tar emot mer trafik kan vi dela upp det för att styra hur tjänsten skalas baserat på specifika trafikmönster.

Det är därför jag tycker om att tänka på klienten som separat från API:et. Detta gör det mycket lätt att tänka på att utveckla för flera plattformar: webb, mobilwebb, iOS, Android, stationära applikationer, tredjepartstjänster etc. De är alla bara klienter som använder samma API.

Till exempel, nu ber våra användare oftast att få släppa en mobilapplikation. Om du separerar klient- och API-entiteterna blir detta enklare.

Så här ser ett sådant system ut:

Hur man skalar från 1 till 100 000 användare

1000 användare: lägg till lastbalanserare

Det ser ljust ut. Graminsta-användare laddar upp fler och fler bilder. Antalet anmälningar ökar också. Vår ensamma API-server har svårt att hänga med i all trafik. Behöver mer järn!

Lastbalanserare är ett mycket kraftfullt koncept. Nyckelidén är att vi sätter en lastbalanserare framför API:t, och den distribuerar trafik till enskilda tjänsteinstanser. Det är så vi skalar horisontellt, vilket innebär att vi lägger till fler servrar med samma kod, vilket ökar antalet förfrågningar vi kan behandla.

Vi kommer att placera separata lastbalanserare framför webbklienten och framför API:et. Detta innebär att du kan köra flera instanser som kör API-kod och webbklientkod. Lastbalanseraren skickar förfrågningar till servern som är mindre laddad.

Här får vi ytterligare en viktig fördel – redundans. När en instans misslyckas (kanske överbelastad eller kraschad) står vi kvar med andra som fortsätter att svara på inkommande förfrågningar. Om det bara fanns en instans som fungerade, skulle hela systemet krascha vid fel.

Lastbalanseraren ger också automatisk skalning. Vi kan konfigurera det för att öka antalet instanser före toppbelastning och minska det när alla användare sover.

Med en lastbalanserare kan API-nivån skalas i det närmaste obegränsad, helt enkelt lägga till nya instanser när antalet förfrågningar ökar.

Hur man skalar från 1 till 100 000 användare

Notera. Just nu är vårt system väldigt likt det som PaaS-företag som Heroku eller Elastic Beanstalk på AWS erbjuder direkt (det är därför de är så populära). Heroku placerar databasen på en separat värd, hanterar en lastbalanserare med automatisk skalning och låter dig vara värd för webbklienten separat från API:et. Detta är en bra anledning att använda Heroku för tidiga projekt eller startups - du får alla grundläggande tjänster ur lådan.

10 000 användare: CDN

Vi borde kanske ha gjort detta från första början. Att behandla förfrågningar och acceptera nya foton börjar belasta våra servrar för mycket.

I det här skedet behöver du använda en molntjänst för att lagra statiskt innehåll – bilder, videor och mycket mer (AWS S3 eller Digital Ocean Spaces). Generellt sett bör vårt API undvika att hantera saker som att visa bilder och ladda upp bilder till servern.

En annan fördel med molnvärd är CDN (AWS kallar detta tillägg Cloudfront, men många molnlagringsleverantörer erbjuder det direkt). CDN cachar automatiskt våra bilder i olika datacenter runt om i världen.

Även om vårt huvudsakliga datacenter kan finnas i Ohio, om någon begär en bild från Japan, kommer molnleverantören att göra en kopia och lagra den i sitt japanska datacenter. Nästa person som begär den här bilden i Japan kommer att få den mycket snabbare. Detta är viktigt när vi arbetar med stora filer, som foton eller videor, som tar lång tid att ladda ner och överföra över hela planeten.

Hur man skalar från 1 till 100 000 användare

100 000 användare: skala datalagret

CDN har hjälpt mycket: trafiken växer i full fart. Den berömda videobloggaren Mavid Mobrick registrerade sig precis hos oss och postade sin "story", som de säger. Tack vare lastbalanseraren hålls CPU- och minnesanvändningen på API-servrarna låg (tio API-instanser körs), men vi börjar få många timeouts på förfrågningar... var kommer dessa förseningar ifrån?

Om vi ​​gräver lite i måtten ser vi att CPU:n på databasservern är 80-90% laddad. Vi är vid gränsen.

Att skala datalagret är förmodligen den svåraste delen av ekvationen. API-servrar betjänar tillståndslösa förfrågningar, så vi lägger helt enkelt till fler API-instanser. Näsa majoritet databaser kan inte göra detta. Vi kommer att prata om populära relationsdatabashanteringssystem (PostgreSQL, MySQL, etc.).

cachelagring

Ett av de enklaste sätten att öka prestandan hos vår databas är att introducera en ny komponent: cachelagret. Den vanligaste cachningsmetoden är ett minneslager för nyckel-värde, som Redis eller Memcached. De flesta moln har en hanterad version av dessa tjänster: Elasticache på AWS och Memorystore på Google Cloud.

En cache är användbar när en tjänst gör många upprepade anrop till databasen för att hämta samma information. I huvudsak kommer vi bara åt databasen en gång, lagrar informationen i cachen och rör den inte igen.

Till exempel, i vår Graminsta-tjänst, varje gång någon går till profilsidan för stjärnan Mobrik, frågar API-servern databasen efter information från hans profil. Detta händer igen och igen. Eftersom Mobriks profilinformation inte ändras vid varje förfrågan är den utmärkt för cachning.

Vi cachelagrar resultaten från databasen i Redis med nyckel user:id med en giltighetstid på 30 sekunder. Nu när någon går till Mobriks profil kontrollerar vi först Redis, och om data finns där överför vi den helt enkelt direkt från Redis. Nu laddar förfrågningar till den mest populära profilen på webbplatsen praktiskt taget inte vår databas.

En annan fördel med de flesta cachningstjänster är att de är lättare att skala än databasservrar. Redis har ett inbyggt Redis Cluster-läge. Liknar en lastbalanserare1, det låter dig distribuera din Redis-cache över flera maskiner (över tusentals servrar om det behövs).

Nästan alla storskaliga applikationer använder caching; det är en absolut integrerad del av ett snabbt API. Snabbare frågebehandling och mer produktiv kod är alla viktiga, men utan cache är det nästan omöjligt att skala en tjänst till miljontals användare.

Läs Replicas

När antalet förfrågningar till databasen har ökat kraftigt, är en sak till vi kan göra att lägga till läsrepliker i databashanteringssystemet. Med de hanterade tjänsterna som beskrivs ovan kan detta göras med ett klick. Läsreplikan förblir aktuell i huvuddatabasen och är tillgänglig för SELECT-satser.

Här är vårt system nu:

Hur man skalar från 1 till 100 000 användare

Nästa steg

När applikationen fortsätter att skala kommer vi att fortsätta att separera tjänsterna för att skala dem oberoende. Till exempel, om vi börjar använda Websockets, är det vettigt att dra Websockets-bearbetningskoden till en separat tjänst. Vi kan placera den på nya instanser bakom vår egen lastbalanserare, som kan skalas upp och ner baserat på öppna Websockets-anslutningar och oavsett antalet HTTP-förfrågningar.

Vi kommer också att fortsätta att bekämpa restriktioner på databasnivå. Det är i detta skede som det är dags att studera databaspartitionering och sönderdelning. Båda tillvägagångssätten kräver ytterligare overhead, men låter dig skala databasen nästan på obestämd tid.

Vi vill också installera en övervaknings- och analystjänst som New Relic eller Datadog. Detta hjälper dig att identifiera långsamma frågor och förstå var förbättringar behövs. När vi skalar vill vi fokusera på att hitta flaskhalsar och eliminera dem – ofta med hjälp av några av idéerna från tidigare avsnitt.

källor

Det här inlägget är inspirerat av en av mina favoritinlägg om hög skalbarhet. Jag ville göra artikeln lite mer specifik för de inledande stadierna av projekt och koppla upp den från en leverantör. Se till att läsa om du är intresserad av detta ämne.

Fotnoter

  1. Även om den liknar belastningsfördelning över flera instanser, är den underliggande implementeringen av ett Redis-kluster mycket annorlunda än en belastningsbalanserare. [lämna tillbaka]

Hur man skalar från 1 till 100 000 användare

Källa: will.com

Lägg en kommentar