Terheléselosztás webkiszolgálókon

A Unix/Linux szerverek üzemeltetése wikiből

Írta: Szluka Péter, 2009. Ez a lap a webszerverek terheléselosztási lehetőségeinek egy részét ismerteti.

Tartalomjegyzék

1 Round Robin DNS

Talán a terheléselosztás legegyszerűbb módja.

Több különálló, önmagában működőképes webszerver esetén használható megoldás. A rendszer speciális forgalomirányító szoftvert nem tartalmaz. Mindegyik szerver IP-címét felvesszük „A” rekordként a DNS-be, a DNS-kiszolgáló mindig más sorrendben ad vissza valamennyi rekordot a konkrét megvalósítástól függően (ez eredendően Round-robin algoritmus alapján történt, innen származik a név).

nslookup www.cnn.com

Server: 192.160.172.6
Address: 192.160.172.6#53

Non-authoritative answer:
Name: www.cnn.com
Address: 157.166.224.25
Name: www.cnn.com
Address: 157.166.224.26
Name: www.cnn.com
Address: 157.166.226.25
Name: www.cnn.com
Address: 157.166.226.26
Name: www.cnn.com
Address: 157.166.255.18
Name: www.cnn.com
Address: 157.166.255.19

nslookup www.cnn.com

Server: 192.160.172.6
Address: 192.160.172.6#53

Non-authoritative answer:
Name: www.cnn.com
Address: 157.166.255.19
Name: www.cnn.com
Address: 157.166.224.25
Name: www.cnn.com
Address: 157.166.224.26
Name: www.cnn.com
Address: 157.166.226.25
Name: www.cnn.com
Address: 157.166.226.26
Name: www.cnn.com
Address: 157.166.255.18

Egyszerű a megvalósítása, és külön költséggel nem jár, (legalábbis a forgalomszabályozás része), viszont vannak korlátai:

Alapesetben nincs visszacsatolás a szerverek állapotáról:

  • Ha egy szerver kiesik, attól még a DNS a hibás szerver címét is visszaadja.
  • Eltérő teljesítményű szerverek esetén nem tudjuk figyelembe venni a teljesítménykülönbségeket.

Ennek elkerülésére létezik megoldás; az LbNamed. A módosított DNS kiszolgáló a szerverek folyamatos lekérdezésével értesül azok terheléséről, majd ezeket az információkat felhasználja a DNS kérésre adott válasz előállítása során.

A kliensek cache-elését nem tudjuk biztosan befolyásolni, nincs mit tenni.

A DNS kiszolgálókban van némi konfigurációs lehetőségünk a sorrend meghatározását illetőlen, pl. BIND esetén:

rrset-order { order_spec ; [ order_spec ; ... ]

ahol az order_spec a következő formájú:

 class class_name ][ type type_name ][ name "domain_name"] order ordering; 

ahol

  • class a rekord osztálya (pl. IN) alapértelmezetten mindegyik szerepel,
  • type a rekord típusa (pl. MX) alapértelmezetten mindegyik szerepel,
  • name a domain.

A rendezés háromfajta értékű lehet:

  • fixed: a zónafájlban lévő sorrendben adja vissza a rekordokat
  • random: véletlenszerűen adja vissza a rekordokat
  • cyclic: Round-robin algoritmus alapján adja vissza a rekordokat

Példa:

rrset-order {type MX name "example.com" order random; order cyclic}; 

Ebben az esetben az MX rekordok véletlenszerűen, a többi Round-robin algoritmus szerint lesz rendezve.


Vagy pl. klienstől függő preferenciát is meghatározhatunk:

sortlist
  {
    {// 1st preference block start
      192.168.4/24; // 1st client IP selection matches any of these
       {10.2/16; // return any of these response IPs as 1st preference
        172.17.4/24; // 2nd preference
       };
    }; // end first block
    
    { // second preference block
     192.168.5/24; // 1st client IP selection matches any of these
      {192.168.4/24; // return any of these response IPs as 1st preference
       172.17.4/24; // 2nd preference
       10.2/16; // 3rd preference
      };
    }; // end second block
  }; // end sortlist

Mivel előfordulhat, hogy a kliens egy munkamenetben(session) más-más szerverekhez fordul, dinamikus webalkalmazások esetén problémát jelenthet a munkamenetek kezelése.

Megoldások:

  • Statikus html használata :)
  • Állapotinformációk tárolása a kliensnél (cookie, paraméterek küldése minden http kérésben) Gyors és olcsó, de csak akkor használható, ha nincs szükség biztonságra, hiszen a felhasználó azt küld vissza, amit akar.
  • Relációs adatbázis használata: Jó megoldás a problémára, biztonságos is, de a skálázhatóságot elrontja: újabb problémát okozunk (ha újabb webkiszolgálót teszünk be, elég lesz az adatbázisszerver kapacitása?)
  • Állapotszerver használata: ASP.NET találmány, majdnem olyan, mint a relációs adatbázis, csak célirányos. A probléma is ugyanaz vele (skálázhatóság)
  • Munkamenet-replikáció (session replication): Az egyes szerverek replikálják a munkameneteket. Többletterhelést okoz a szerverek közötti replikáció, és a skálázhatóság itt is csökken.


2 Adatkapcsolati rétegbeli (layer 2) megoldások

Abban az esetben, ha olyan szolgáltatást nyújtunk, ahol a legszűkebb keresztmetszet a hálózati sávszélesség, tehát a szerverek többi erőforrása alkalmas lenne további felhasználók kiszolgálására, alkalmazhatunk többszörözési technikákat, mint pl.:

Ezek lényege, hogy két, vagy több csatornát azok összefogásával egyetlen nagy sávszélességű csatornává alakítanak, az így kialakuló csatorna gyorsaságán kívül a megvalósítástól függő mértékben redundáns is lesz.

Jellegükből adódóan nem csak webkiszolgálók terheléselosztására használhatók.


3 Szállítási rétegbeli (layer 4) megoldások

A szállítási rétegbeli megoldások a TCP/IP csomagok szétválogatásán, és azok célszerverekre való továbbításán alapulnak. Jellegükből adódóan nem csak webkiszolgálók terheléselosztására használhatók.

Linuxon az LVS ilyen megoldást nyújt.

A megoldás lényege, hogy a kliensek egy speciális szerverhez fordulnak, az ún. virtuális szerverhez. Ezen a szerveren egy forgalomszabályozó program fut, ami megvizsgálja a beérkező TCP/IP csomagokat, (pl. célport, forrás IP, stb.) és a benne található információk, valamint a konfiguráció alapján a csomagot a kéréseket valóban feldolgozó szerverek egyikéhez irányítja.A virtuális szerver működésének jellegéből adódóan layer2 alapú gyorsítással remekül növelhető a teljesítménye.

Az irányítás és a válasz módjától függően a megoldás további altípusokra bontható:


3.1 Virtual server VIA NAT

A megoldás lényege, hogy a virtuális szerver (VS) két interfésszel rendelkezik, az egyik a külső hálózathoz, a másik egy belső hálózathoz csatlakozik, és egy - a hálózati címfordításhoz nagyon hasonló - eljárást végez.


VS-NAT.gif
forrás: VS-NAT.gif


A belső hálózaton találhatóak a valódi kiszolgálók, a kérések a VS-hez érkeznek. A VS-en futó szoftver a konfiguráció alapján kiválasztja, hogy melyik valós szerver fogja kiszolgálni a kérést, és az IP csomagok célcímét, TCP/UDP portját ennek megfelelően írja át, majd továbbítja a belső hálózatra, valamint bejegyzést készít a kapcsolatról.

A valós szerver megkapja a csomagokat, azokra válaszol, mintha egyedüli szerver lenne, a válasz csomagok a routing tábla alpján a VS-en keresztül jutnak el a célhoz, azonban a VS a kimenő csomagok forrás címét saját címére módosítja.

Probléma: Mi történik akkor, ha a kliens ugyanazon a hálózaton van, mint a valós szerverek?

3.2 Virtual server via Tunneling

Abban az esetben, ha a szerverek földrajzilag elkülönítettek, célszerűbb a NAT eljárás helyett a tunneling módszert választani.


VS-IPTunneling.gif
forrás: VS-IPTunneling.gif


A külső kérések ebben az esetben is a VS virtuális IP címére (VIP) érkeznek. A VS a beérkező csomagokat a megfelelő valós szerverek egyikéhez irányítja, mégpedig úgy, hogy az eredeti csomagot egy kiegészítő IP fejléccel látja el (IP over IP, IPIP), majd ezt küldi tovább a valós szervernek:


VS-TUN-flow.jpg
forrás: VS-TUN-flow.jpg


A valós szerver megkapja a csomagot, leválasztja a kiegészítő fejlécet, és az így kapott csomagot úgy kezeli, mintha közvetlenül a klienstől érkezett volna, közvetlenül válaszol rá. Ahhoz, hogy ezt problémamentesen meg tudja tenni, (tudja, hogy neki szól a csomag, és forrás címként a VIP címet írja) definiálnia kell egy olyan interfészt, (általában loopback / dummy alias) amelynek IP címe a VIP. Ezzel lesz még probléma, ugyanis innentől kezdve az adott interfész válaszolni fog az ARP-kérésekre, ami nem jó, különösen akkor, ha egy hálózaton van legalább egy valós szerver és a virtuális szerver. Később részletesebben foglalkozunk a kérdéssel.

3.3 Virtual Server via Direct Routing

Abban az esetben, ha a valódi szerverek egy hálózaton vannak, gyorsabb megoldást jelent a Direct Routing.


VS-DRouting.gif
forrás: VS-DRouting.gif


Ennek során a VS a beérkező csomagokat tovább irányítja a megfelelő valós szerverhez, mégpedig úgy, hogy a teljes TCP/IP csomagot tovább küldi a cél szerver MAC címére. A valós szervereken egy loopback alias-ként a VIP címet kell beállítani, így a szerverek felismerik, hogy nekik szól a csomag, és arra közvetlenül válaszolnak.

Természetesen itt is megjelenik az előbb is ismertetett probléma, a szerverek válaszolnak az ARP-kérésekre.


3.4 Az ARP-probléma

Abban az esetben, ha egy hálózaton van virtuális szerver, valamint legalább egy valós szerver és a direct routing, vagy a tunneling módszert használjuk, egy hálózaton több VIP című szerver lesz, a valós szerverek alapesetben válaszolni fognak az ARP-kérésekre, ami nem jó, mert versenyhelyzet adódik.

Előfordulhat, hogy a külső kliensek közvetlenül a valós szerverekhez jutnak el, így a forgalomirányítás használhatatlanná válik.

- Régi kernel esetén (2.0.x) ha loopback aliasként konfiguráljuk a VIP címet nincsen gond, mivel nem válaszol a loopback alias és tunneling ARP-kérésekre.

- 2.2.x kernel verziótól válaszol, egy lehetséges megoldás, hogy letiltjuk valahogyan:

#Start the hiding interface functionality
echo 1 > /proc/sys/net/ipv4/conf/all/hidden
# Hide all addresses for this interface
echo 1 > /proc/sys/net/ipv4/conf/<interface_name>/hidden

Természetesen ez csak akkor használható normál hálózati csatoló esetén, ha a szerverekben több hálózati csatoló van. Érdmes ezért vagy dummy / loopback aliast létrehozni, és azok ARP-válaszát kitiltani.

Vagy használhatjuk az iproute-ot: /etc/sysctl.conf:

net.ipv4.conf.all.arp_ignore = 1;
net.ipv4.conf.eth0.arp_ignore = 1;
net.ipv4.conf.all.arp_announce = 2;
net.ipv4.conf.eth0.arp_announce = 2;

4 Alkalmazási rétegbeli (layer 7) módszerek

4.1 Selective Source NAT

A NAT módszer esetén láthattuk, hogy problémát jelent, ha a kapcsolódó kliens egy hálózaton van a valós szerverekkel, ugyanis azok így közvetlenül a kliensnek küldik a választ, a virtuális szerver nem értesül a kapcsolat lezárásáról. Azt, hogy ilyen eset (egy hálózaton van a kliens a szerverekkel) miért fordul elő (ingyen van a belső célra használható IP, a switchek vagy tudnak VNAT-ot, vagy olcsók) kérdéses, mindenesetre van megoldás, a Selective SNAT, itt most nem részletezném. Bővebben: http://lbdigest.com/2009/03/11/best-of-both-worlds-selective-source-nat/

4.2 KTCPVS

A webszerverekben egy-egy kérés kiszolgálásához általában a következő háromfajta műveletre lehet szükség:

  • tartalom (szöveg) betöltése egy diszkről
  • képek betöltése egy diszkről
  • alkalmazások futtatása

Ezeket a funkciókat szétválogathatjuk, az egyes részfeladatokat az adott célra optimalizált szerverekre bízhatjuk. A kliensek közvetlenül a load balancer-hez fordulnak, ahol kernel thread-ként fut az ütemező, a különböző kéréseket különböző szerverekhez továbbítja, a visszakapott válaszokat pedig visszaküldi a kliensnek:

Ktcpvs impl.jpg
forrás: Ktcpvs_impl.jpg


Az adminisztráció egy userspace-beli programmal történhet. Példa 3 szerverre: web1 (képek), web2 (html), web3 (többi)):

tcpvsadm -A -i http -s http
tcpvsadm -a -i http -r web1:80
tcpvsadm -a -i http -r web2:80
tcpvsadm -a -i http -r web3:80
tcpvsadm --add-rule -i http --pattern=/images/.* -r web1:80
tcpvsadm --add-rule -i http --pattern=/html/.* -r web2:80
tcpvsadm --add-rule -i http --pattern=.* -r web3:80

4.3 SSL termination, SSL célhardverek

A https-kapcsolatok kezelésénél a titkosítás nagy terhelést jelent a szerverek számára.

Érdemes lehet az SSL-kapcsolatok kezelését a forgalomszabályozón elvégezni, így a szervereken kisebb a terhelés. Ezt célszerűen akkor érdemes elvégezni, ha a forgalomszabályozó processzora elegendően gyors, vagy tartalmaz olyan célhardvert, ami az SSL titkosítást gyorsítja.

Load Balancing with SSL Termination at the Cisco ACE.jpg
forrás: http://docwiki.cisco.com/wiki/Image:Load_Balancing_with_SSL_Termination_at_the_Cisco_ACE.jpg


4.4 Apache mod_proxy_balancer

Az apache mod_proxy modulja proxy-képességekkel ruházza fel az apache kiszolgálót. Képes forward és reverse proxyként is működni; terheléselosztás szempontjából a reverse proxy funkció érdekes. A reverse proxy gyakorlatilag a forward proxy szerverkörnyezetbeli megfelelője: míg a forward proxy belső gép(ek) számára végez kéréseket a nyilvános hálózaton, ezek eredményeit esetleg cache-eli, addig a reverse proxy a belső hálózaton található szerverek felé továbbítja a nyilvános hálózatról érkezett kéréseket, majd azok válaszát visszaküldi a kliens számára. Látható, hogy ez remekül használható forgalomelosztásra is.


A mod_proxy direktívái közül számunkra a következő három fontos:

  • ProxyRequests (on/off): Off-al kikapcsoljuk a forward proxy-t, ami felesleges forgalomszabályozáshoz.
  • ProxyPass: Átírja a beérkező kérés url-jét

Ha a lokális szerver címe pl: http://example.com/, akkor a

ProxyPass /mirror/foo/ http://backend.example.com/ 

hatására a http://example.com/mirror/foo/bar címre érkező kérések a http://backend.example.com/bar címre irányítódnak Ez már jó valamennyire, de még nem tökéletes, mit tegyünk, ha egy alkönyvtár kiszolgálására sem elég egyetlen szerver?

  • BalanceMember: (Apache 2.2-től)
BalancerMember [balancerurl] url [key=value [key=value ...]]

A key=value paraméterek a ProxyPass direktíva paraméterei lehetnek.

Példa:

ProxyPass /special-area http://special.example.com/ smax=5 max=10
ProxyPass / balancer://mycluster/ stickysession=JSESSIONID|jsessionid nofailover=On
<Proxy balancer://mycluster>
BalancerMember http://1.2.3.4:8009
BalancerMember http://1.2.3.5:8009 smax=10
# Less powerful server, don't send as many requests there
BalancerMember http://1.2.3.6:8009 smax=1 loadfactor=20
</Proxy>


A ProxyPass direktíva paraméterei:

  • min legalább ennyi kapcsolatot mindig nyitva tart a backend szerveren
  • max Hard maximuma a megnyitható kapcsolatoknak
  • smax Soft maximuma a megnyitható kapcsolatoknak, ennyi keletkezik
  • acquire (msec): legfeljebb ennyi ideig vár egy szabad kapcsolatra a pool-ból. Ha nincs szabad kapcsolat, akkor SERVER_BUSY státuszt küld
  • connectiontimeout: (sec) a backend szerver kapcsolódására ennyit vár maximum
  • disablereuse (on/off) azonnal lezárja a kapcsolatot a backend szerverrel használat után
  • flushpackets (on/off/auto)
  • flushwait (msec) ha a flushpackets auto ennyi ideig vár újabb inputra
  • keepalive (on/off) firewall alkalmazása esetén megakadályozza az inaktív kapcsolatok megszakítását KEEP_ALIVE üzenetek küldésével
  • lbset
  • ping
  • loadfactor: Dolgozó normalizált terhelhetősége, BalanceMember-el együtt használható, 1-100 ig terjedő szám lehet
  • redirect: Átirányítás, általában dinamikusan állítódik be egy csomópont biztonságos eltávolításakor
  • retry (sec): Ha hibát jelez valamelyik worker, akkor ennyi ideig vár, mielőtt újra megpróbálná.
  • route: út a worker-hez (session id-hez kötött)
  • status: karakterekből álló jelzés, a worker állapotát jelzi, a következő karakterekből állhat:
    • D (disabled)
    • S (stopped)
    • I (Ignore errors)
    • H (Hot-standby)
    • E (Error state)
    • + Egy tulajdonság engedélyezése (default)
    • - Egy tulajdonság törlése
  • timeout (sec): az Apache ennyi ideig vár a backend-től érkező adatra
  • ttl:

mod_proxy_balancer specifikus

  • lbmethod: A balancer ütemezésének működési módja
    • byrequests (default)
    • bytraffic
    • bybusyness
  • maxattempts: Ennyi próbálkozás után adja fel
  • nofailover (on/off): on esetén a session megszakad, ha a worker meghibásodik, akkor kellhet, ha nincs session replication
  • stickysession: A session-ök kezeléséhez szükséges alkalmazásszervereknél. Ha eltérő nevű a cookie és az url-be kódolt id, akkor | jellel elválasztva adható meg külön-külön
  • timeout (sec): A forgalomelosztó maximum ennyit vár a worker-re.

Megjegyzés: természetesen egyéb lehetőségek is vannak, pl.: a lighttpd

5 A legszűkebb keresztmetszet

Nem szabad megfeledkezni arról, hogy az utóbbi módszerek mindegyike egy forgalomirányítót tartalmaz, aminek meghibásodása esetén az egész fürt használhatatlanná válik. Általában elmondható, hogy ahol a látogatók nagy száma miatt terheléselosztást kell végezni, ott a rendelkezésre állási igény is magas, ezért érdemes lehet a forgalomirányítóból legalább kettőt üzemeltetni, vagy legalább hideg-tartalékot képezni.


6 Források:

Személyes eszközök