Programmering

Lastbalanseringsarkitekturer for server, del 1: Lastbalansering på transportnivå

Serverfarmene oppnår høy skalerbarhet og høy tilgjengelighet gjennom serverbalansering, en teknikk som gjør at serverfarm fremstår for klienter som en enkelt server. I denne todelte artikkelen utforsker Gregor Roth serverbelastningsbalanseringsarkitekturer, med fokus på løsninger med åpen kildekode. Del 1 dekker det grunnleggende om serverbalansering og diskuterer fordeler og ulemper med serverbalansering av servernivå. Del 2 dekker applikasjonsnivå serverbelastningsarkitekturer, som adresserer noen av begrensningene til arkitekturen diskutert i del 1.

Inngangshindringen for mange internettbedrifter er lav. Alle med en god ide kan utvikle et lite program, kjøpe et domenenavn og sette opp noen PC-baserte servere for å håndtere innkommende trafikk. Den opprinnelige investeringen er liten, så oppstartsrisikoen er minimal. Men en vellykket billig infrastruktur kan raskt bli et alvorlig problem. En enkelt server som håndterer alle innkommende forespørsler, har kanskje ikke kapasitet til å håndtere høye trafikkvolumer når virksomheten blir populær. I slike situasjoner begynner bedrifter ofte å skalere opp: de oppgraderer eksisterende infrastruktur ved å kjøpe en større boks med flere prosessorer eller legge til mer minne for å kjøre applikasjonene.

Å skalere opp er imidlertid bare en kortsiktig løsning. Og det er en begrenset tilnærming fordi kostnadene ved oppgradering er uforholdsmessig høye i forhold til gevinsten i serverfunksjonalitet. Av disse grunner følger de mest vellykkede internettbedriftene a skalere ut nærme seg. Applikasjonskomponenter behandles som flere forekomster på serverfarmene, som er basert på billig maskinvare og operativsystemer. Når trafikken øker, blir servere lagt til.

Server-farm-tilnærmingen har sine egne unike krav. På programvaresiden må du designe applikasjoner slik at de kan kjøre som flere forekomster på forskjellige servere. Du gjør dette ved å dele applikasjonen i mindre komponenter som kan distribueres uavhengig. Dette er trivielt hvis applikasjonskomponentene er statsløse. Fordi komponentene ikke beholder noen transaksjonstilstand, kan noen av dem håndtere de samme forespørslene likt. Hvis det kreves mer prosessorkraft, legger du bare til flere servere og installerer applikasjonskomponentene.

Et mer utfordrende problem oppstår når applikasjonskomponentene er stateful. For eksempel, hvis applikasjonskomponenten inneholder handlekurvdata, må en innkommende forespørsel dirigeres til en applikasjonskomponentforekomst som inneholder den rekvirentens handlekurvdata. Senere i denne artikkelen vil jeg diskutere hvordan man håndterer slike applikasjonsøktsdata i et distribuert miljø. For å redusere kompleksiteten prøver de mest vellykkede internettbaserte applikasjonssystemene å unngå stateful applikasjonskomponenter når det er mulig.

På infrastruktursiden må behandlingsbelastningen fordeles på gruppen av servere. Dette er kjent som serverbalansering. Lastbalanseringsteknologier gjelder også andre domener, for eksempel spredning av arbeid blant komponenter som nettverkskoblinger, CPUer eller harddisker. Denne artikkelen fokuserer på serverbalansering.

Tilgjengelighet og skalerbarhet

Serverbelastningsfordeling distribuerer tjenesteforespørsler på tvers av en gruppe ekte servere og får disse serverne til å se ut som en enkelt stor server for klientene. Ofte er dusinvis av ekte servere bak en URL som implementerer en enkelt virtuell tjeneste.

Hvordan virker dette? I en mye brukt serverbalanseringsarkitektur, blir den innkommende forespørselen rettet til en dedikert serverbelastningsbalanser som er gjennomsiktig for klienten. Basert på parametere som tilgjengelighet eller gjeldende serverbelastning, bestemmer lastbalanseren hvilken server som skal håndtere forespørselen og videresender den til den valgte serveren. For å gi lastbalanseringsalgoritmen de nødvendige inngangsdataene, henter lastbalanseren også informasjon om servernes helse og belastning for å verifisere at de kan svare på trafikk. Figur 1 illustrerer denne klassiske arkitekturen for lastbalansering.

Lastutleveringsarkitekturen illustrert i figur 1 er bare en av flere tilnærminger. For å bestemme hvilken lastbalanseringsløsning som er best for infrastrukturen din, må du vurdere tilgjengelighet og skalerbarhet.

Tilgjengelighet er definert av oppetid - tiden mellom feil. (Nedetid er tiden for å oppdage feilen, reparere den, utføre nødvendig gjenoppretting og starte oppgaver på nytt.) Under oppetid må systemet svare på hver forespørsel innen en forutbestemt, veldefinert tid. Hvis denne tiden overskrides, ser klienten dette som en serverfeil. Høy tilgjengelighet er i utgangspunktet redundans i systemet: hvis en server mislykkes, tar de andre over den mislykkede serverens belastning transparent. Feilen til en enkelt server er usynlig for klienten.

Skalerbarhet betyr at systemet kan betjene en enkelt klient, i tillegg til tusenvis av samtidige klienter, ved å oppfylle kvalitetskrav til tjenesten, for eksempel svartid. Under økt belastning kan et høyt skalerbart system øke gjennomstrømningen nesten lineært i forhold til kraften til ekstra maskinvareressurser.

I scenariet i figur 1 oppnås høy skalerbarhet ved å distribuere den innkommende forespørselen over serverne. Hvis belastningen øker, kan flere servere legges til, så lenge belastningsbalansen ikke blir flaskehalsen. For å oppnå høy tilgjengelighet må belastningsutjevneren overvåke serverne for å unngå å videresende forespørsler til overbelastede eller døde servere. Videre må selve lastutjevneren også være overflødig. Jeg vil diskutere dette poenget senere i denne artikkelen.

Serverbelastningsteknikker

Generelt er serverlastbalanseringsløsninger av to hovedtyper:

  • Transportnivå lastbalansering - for eksempel den DNS-baserte tilnærmingen eller TCP / IP-nivå-balansering - fungerer uavhengig av applikasjonsnyttelasten.
  • Søknadsnivå lastbalansering bruker applikasjonsnyttelasten til å ta beslutninger om belastningsbalansering.

Lastbalanseringsløsninger kan videre klassifiseres i programvarebasert lastbalansering og maskinvarebasert lastbalansering. Maskinvarebasert lastbalanseringsapparat er spesialiserte maskinvarebokser som inkluderer applikasjonsspesifikke integrerte kretser (ASIC) tilpasset for en bestemt bruk. ASIC-er muliggjør videresending av nettverkstrafikk raskt uten omkostningene til et generelt operativsystem. Maskinvarebasert lastbalansering brukes ofte til lastbalansering på transportnivå. Generelt er maskinvarebaserte lastbalansere raskere enn programvarebaserte løsninger. Ulempen deres er kostnadene.

I motsetning til maskinvare belastningsbalansere, kjøres programvarebaserte belastningsbalansere på standard operativsystemer og standard maskinvarekomponenter som PCer. Programvarebaserte løsninger kjører enten innenfor en dedikert maskinvarenode for lastbalansering som i figur 1, eller direkte i applikasjonen.

DNS-basert lastbalansering

DNS-basert belastningsbalansering representerer en av de tidlige tilnærmingene for serverbalanse. Internets domenenavnssystem (DNS) knytter IP-adresser til et vertsnavn. Hvis du skriver inn et vertsnavn (som en del av URL-en) i nettleseren din, ber nettleseren om at DNS-serveren løser vertsnavnet til en IP-adresse.

Den DNS-baserte tilnærmingen er basert på det faktum at DNS tillater at flere IP-adresser (ekte servere) tildeles ett vertsnavn, som vist i DNS-oppslagseksemplet i liste 1.

Oppføring 1. Eksempel på DNS-oppslag

> nslookup amazon.com Server: ns.box Adresse: 192.168.1.1 Navn: amazon.com Adresser: 72.21.203.1, 72.21.210.11, 72.21.206.5

Hvis DNS-serveren implementerer en round-robin-tilnærming, endres rekkefølgen på IP-adressene for en gitt vert etter hvert DNS-svar. Vanligvis prøver klienter som nettlesere å koble til den første adressen som returneres fra et DNS-spørsmål. Resultatet er at svar på flere klienter distribueres mellom serverne. I motsetning til serverens belastningsbalanseringsarkitektur i figur 1, er det ikke nødvendig med en mellomliggende lastbalanserings maskinvarenode.

DNS er en effektiv løsning for global serverbelastningsbalansering, der belastning må fordeles mellom datasentre på forskjellige steder. Ofte kombineres den DNS-baserte globale serverbalanseringen med andre serverbalanseringsløsninger for å distribuere belastningen i et dedikert datasenter.

Selv om det er enkelt å implementere, har DNS-tilnærmingen alvorlige ulemper. For å redusere DNS-spørsmål, har klienten en tendens til å cache DNS-spørsmålene. Hvis en server blir utilgjengelig, vil klientbufferen og DNS-serveren fortsette å inneholde en død serveradresse. Av denne grunn gjør DNS-tilnærmingen lite for å implementere høy tilgjengelighet.

TCP / IP-serverbalanse

TCP / IP-serverbalanseringsvektorer fungerer på lavnivåskift. En populær programvarebasert serverbalanse for lavt nivå er Linux Virtual Server (LVS). De virkelige serverne fremstår for omverdenen som en enkelt "virtuell" server. De innkommende forespørslene på en TCP-tilkobling blir videresendt til de virkelige serverne av lastbalanseren, som kjører en Linux-kjerne lappet for å inkludere IP Virtual Server (IPVS) -kode.

For å sikre høy tilgjengelighet er det i de fleste tilfeller satt opp et par belastningsbalanseringsnoder, med en belastningsbalanseringsnode i passiv modus. Hvis en belastningsutjevner mislykkes, aktiverer hjerterytmeprogrammet som kjører på begge belastningsutjevnere den passive lastutjevningsnoden og starter overtakelsen av den virtuelle IP-adressen (VIP). Mens hjerterytmen er ansvarlig for å håndtere failover mellom lastbalanseringsapparatene, brukes enkle send / forvent-skript for å overvåke helsen til de virkelige serverne.

Gjennomsiktighet til klienten oppnås ved å bruke en VIP som er tildelt belastningsutjevneren. Hvis klienten sender ut en forespørsel, blir først det valgte vertsnavnet oversatt til VIP. Når den mottar forespørselpakken, bestemmer lastbalanseren hvilken ekte server som skal håndtere forespørselspakken. Mål-IP-adressen til forespørselspakken blir skrevet om til den virkelige IP-en (RIP) til den virkelige serveren. LVS støtter flere planleggingsalgoritmer for distribusjon av forespørsler til de virkelige serverne. Det er ofte satt opp til å bruke round-robin planlegging, i likhet med DNS-basert lastbalansering. Med LVS tas beslutning om lastbalansering på TCP-nivå (lag 4 i OSI-referansemodellen).

Etter å ha mottatt forespørselpakken, håndterer den virkelige serveren den og returnerer svarpakken. For å tvinge svarpakken til å bli returnert gjennom lastbalansen, bruker den virkelige serveren VIP som standard svarrute. Hvis belastningsutjevneren mottar svarpakken, blir kilden IP til svarpakken omskrevet med VIP (OSI Model Layer 3). Denne LVS-rutemodus kalles NAT-ruting (Network Address Translation). Figur 2 viser en LVS-implementering som bruker NAT-ruting.

LVS støtter også andre rutemoduser som Direkte serverretur. I dette tilfellet blir svarpakken sendt direkte til klienten av den virkelige serveren. For å gjøre dette må VIP også tildeles alle virkelige servere. Det er viktig å gjøre serverens VIP uoppløselig for nettverket; Ellers blir lastutjevneren utilgjengelig. Hvis belastningsutjevneren mottar en forespørselspakke, blir MAC-adressen (OSI Model Layer 2) til forespørselen omskrevet i stedet for IP-adressen. Den virkelige serveren mottar forespørselspakken og behandler den. Basert på kilde-IP-adressen, blir svarpakken sendt til klienten direkte, utenom belastningsbalansen. For webtrafikk kan denne tilnærmingen redusere balansegangsarbeidet dramatisk. Vanligvis overføres mange flere svarpakker enn forespørselpakker. For eksempel, hvis du ber om en webside, sendes ofte bare en IP-pakke. Hvis du ber om en større webside, kreves det flere IP-pakker for svar for å overføre den forespurte siden.

Caching

Servernivåløsningsløsere på lavt nivå, for eksempel LVS, når grensen hvis caching på applikasjonsnivå eller støtte for applikasjonssessioner er nødvendig. Caching er et viktig skalerbarhetsprinsipp for å unngå dyre operasjoner som henter samme data gjentatte ganger. En hurtigbuffer er en midlertidig butikk som inneholder overflødige data som følge av en tidligere datahenting. Verdien på en hurtigbuffer avhenger av kostnaden for å hente dataene mot trefffrekvensen og den nødvendige bufferstørrelsen.

Basert på planleggingsalgoritmen for lastbalanser, håndteres forespørslene fra en brukerøkt av forskjellige servere. Hvis en cache brukes på serversiden, vil avvikende forespørsler bli et problem. En tilnærming for å håndtere dette er å plassere hurtigbufferen i et globalt rom. memcached er en populær distribuert cache-løsning som gir en stor cache på tvers av flere maskiner. Det er en partisjonert, distribuert cache som bruker jevn hashing for å bestemme cache-serveren (daemon) for en gitt cacheoppføring. Basert på hurtignøkkelens hash-kode, tilordner klientbiblioteket alltid den samme hash-koden til samme cache-serveradresse. Denne adressen brukes deretter til å lagre cacheoppføringen. Figur 3 illustrerer denne caching-tilnærmingen.

Oppføring 2 bruker spymemcached, a memcached klient skrevet i Java for å cache HttpResponse meldinger på tvers av flere maskiner. De spymemcached biblioteket implementerer den nødvendige klientlogikken jeg nettopp beskrev.

Oppføring 2. memcached-basert HttpResponse cache

$config[zx-auto] not found$config[zx-overlay] not found