2014-10-16 11 views
14

Używamy Nginx jako load-balancer dla naszej aplikacji websocket. Każdy serwer zaplecza przechowuje informacje o sesji, więc każde żądanie klienta musi zostać przekazane na tym samym serwerze. Więc używamy dyrektywy ip_hash do osiągnięcia tego celu:Nginx, równoważenie obciążenia za pomocą algorytmów lepkich i najmniejszych połączeń jednocześnie.

upstream app { 
    ip_hash; 
    server 1; 
} 

Problem pojawia się, gdy chcemy dodać kolejny serwer backend:

upstream app { 
    ip_hash; 
    server 1; 
    server 2; 
} 

Nowe połączenia przejść do serwera 1 i serwer 2 - ale to nie to, co jest potrzebujemy w tej sytuacji, ponieważ obciążenie na serwerze 1 wciąż rośnie - wciąż potrzebujemy lepkich sesji, ale też włączono algorytm least_conn - więc nasze dwa serwery otrzymują w przybliżeniu jednakowe obciążenie.

Rozważaliśmy także użycie Nginx-sticky-module, ale dokumentacja mówi, że jeśli nie będzie dostępny żaden lepki plik cookie, to powróci on do domyślnego algorytmu Nginx, tak więc nie rozwiązuje problemu.

Pytanie więc, czy możemy połączyć lepszą i najmniejszą logikę połączeń za pomocą Nginx? Czy wiesz, które inne moduły równoważenia obciążenia rozwiązują ten problem?

+0

Być może to powinno zostać przeniesione do serverfault, aby uzyskać odpowiedź? – Collector

+0

Interesujące pytanie brzmi: "obciążenie serwera 1 wzrasta" - czy większość użytkowników może korzystać z tego samego lub kilku adresów NAT? W tym przypadku hashing na źródłowym IP jest po prostu nieefektywny i możesz rozważyć użycie bardziej wyrafinowanego klucza za pośrednictwem 'hash' dyrekty w przeciwieństwie do' ip_hash '. Na przykład możesz chcieć dodać część klucza URI użytkownika do danego klucza ... – wick

+0

Przydatne odpowiedzi, ale nie jestem pewien, czy odpowiedzieli na pierwotnie zadane pytanie. Alex? –

Odpowiedz

5

Prawdopodobnie za pomocą modułu split_clients może pomóc

upstream app { 
    ip_hash; 
    server 127.0.0.1:8001; 
} 

upstream app_new { 
    ip_hash; 
    server 127.0.0.1:8002; 
} 

split_clients "${remote_addr}AAA" $upstream_app { 
    50% app_new; 
    * app; 
} 

ten zostanie podzielony ruch i utworzyć zmienną $upstreap_app ten, można użyć jak:

server { 
    location /some/path/ { 
    proxy_pass http://$upstream_app; 
} 

Jest to obejście do least_conn i system równoważenia obciążenia działający z lepkimi sesjami, "wadą" jest to, że jeśli trzeba dodać więcej serwerów, należy utworzyć nowy strumień, na przykład:

split_clients "${remote_addr}AAA" $upstream_app { 
    30% app_another_server; 
    30% app_new; 
    * app; 
} 

badania:

for x in {1..10}; do \ 
    curl "0:8080?token=$(LC_ALL=C; cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)"; done 

Więcej informacji na temat tego modułu można znaleźć w tym artykule (Performing A/B testing)

+0

Uwaga, 'split_clients' użyje spójnego hashu do równoważenia obciążenia, które może, ale nie musi być lepsze niż round-robin, ale NIE jest tym, o co prosi (bilansowanie oparte na minimum_connect) – wick

4

Można łatwo osiągnąć stosując HAProxy a ja rzeczywiście sugerują dzieje through it thoroughly aby zobaczyć, jak Twoja obecna konfiguracja może przynieść korzyści.

Ha Proxy, że masz coś takiego:

backend nodes 
    # Other options above omitted for brevity 
    cookie SRV_ID prefix 
    server web01 127.0.0.1:9000 cookie check 
    server web02 127.0.0.1:9001 cookie check 
    server web03 127.0.0.1:9002 cookie check 

co oznacza po prostu, że pełnomocnik jest śledzenie żądań i z powrotem serwery za pomocą plików cookie.

Jednakże, jeśli nie chcesz używać HAProxy, sugeruję, abyś skonfigurował zmianę implementacji sesji, tak aby korzystała z DB w pamięci, na przykład redis/memcached. W ten sposób możesz użyć najmniejszego lub dowolnego innego algorytmu bez martwienia się o sesje.