Terheléselosztás webkiszolgálókon

A Unix/Linux szerverek üzemeltetése wikiből
(Változatok közti eltérés)
(Apache mod_proxy_balancer)
262. sor: 262. sor:
 
ProxyPass /mirror/foo/ http://backend.example.com/
 
ProxyPass /mirror/foo/ http://backend.example.com/
 
</pre>
 
</pre>
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
+
hatására a <nowiki>http://example.com/mirror/foo/bar</nowiki> címre érkező kérések a <nowiki>http://backend.example.com/bar</nowiki> 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?
 
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?
   
324. sor: 324. sor:
 
* timeout (sec): A forgalomelosztó maximum ennyit vár a worker-re.
 
* 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 http://www.lighttpd.net/]
+
'''Megjegyzés:''' természetesen egyéb lehetőségek is vannak, pl.: a [[lighttpd http://www.lighttpd.net/]]
   
 
== A legszűkebb keresztmetszet ==
 
== A legszűkebb keresztmetszet ==

A lap 2009. december 9., 21:22-kori változata

Terheléselosztás webkiszolgálóknál


Tartalomjegyzék

1 Round Robin (változó) DNS

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

Több különálló, önmagában működőképes webszerverek esetén használható megoldás. A szerverek speciális szoftvert nem tartalmaznak, mindegyiknek külön IP címe van. Mindegyik szerver IP címét felvesszük „A” rekordként a DNS-be, a DNS kiszolgáló mindig másik címet ad vissza megvalósítástól függően (Általában, de nem feltétlenül Round-robin algoritmus alapján, innen is 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 http://www.stanford.edu/~riepel/lbnamed/ A módosított DNS kiszolgáló a szerverek folyamatos lekérdezésével értesül azok terheléséről, 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őleg, pl. BIND esetén:


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


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 más-más szerverekhez fordul, dinamikus web alkalmazá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ázis szerver 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álás: Az egyes szerverek replikálják a munkameneteket. Plusz terhelést okoz a szerverek közötti replikáció, és a skálázhatóság itt is csökken.


2 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.:

link aggregation, port aggregation, etherchannel, gigabit etherchannel port bundling.

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éből adódóan szintén nem csak webkiszolgáló célokra használható.


3 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élszerverre való továbbításán alapulnak. Jellegéből adódóan szintén nem csak www célokra használhatóak.


Linuxon az LVS http://www.linuxvirtualserver.org 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: http://www.linuxvirtualserver.org/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: http://www.linuxvirtualserver.org/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: http://www.linuxvirtualserver.org/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: http://www.linuxvirtualserver.org/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 3.2, vagy 3.3 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 Layer 7 módszerek

4.1 Selective Source NAT

A 3.1 módszer esetén 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 www szerverek általában 3 fő feladatot végeznek: tartalom (szöveg) betöltése, képek betöltése, alkalmazások futtatása.

Lehetséges, hogy ezeket a funkciókat szétválogassuk, és külön szerverekre helyezzük, így az egyes szerverek jobban optimalizálhatóak. 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: http://kb.linuxvirtualserver.org/images/5/55/Ktcpvs_impl.jpg


Az adminisztráció egy user space 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ó cpu teljesítménye nagy, 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 funkcionálni, terheléselosztás szempontjából a reverse proxy funkció érdekes. A reverse proxy gyakorlatilag a forward proxy szerver kö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 három fontos:

  • ProxyRequest (on/off): Off-al kikapcsoljuk a reverse proxy-t, ami hasznos ebben az esetben
  • 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): a maximum idő, amit 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 http://www.lighttpd.net/

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 az ilyen teljesítmény igényeknél általában a rendelkezésre állási igény is magas, ezért érdemes lehet


6 Irodalom, további információk:

Személyes eszközök