2014-10-16 20 views
14

Chúng tôi sử dụng Nginx làm bộ cân bằng tải cho ứng dụng websocket của chúng tôi. Mỗi máy chủ phụ trợ giữ thông tin phiên vì vậy mọi yêu cầu từ khách hàng phải được chuyển tiếp trên cùng một máy chủ. Vì vậy, chúng tôi sử dụng ip_hash chỉ thị để đạt được điều này:Nginx, cân bằng tải bằng cách sử dụng các thuật toán dính và ít nhất kết nối đồng thời

upstream app { 
    ip_hash; 
    server 1; 
} 

Vấn đề xuất hiện khi chúng ta muốn thêm một máy chủ backend:

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

kết nối mới đi đến máy chủ 1 và máy chủ 2 - nhưng điều này không phải những gì là chúng tôi cần trong tình huống này khi tải trên máy chủ 1 tiếp tục tăng - chúng tôi vẫn cần các phiên cố định nhưng cũng bật thuật toán least_conn - vì vậy hai máy chủ của chúng tôi nhận được khoảng tải bằng nhau.

Chúng tôi cũng xem xét sử dụng Nginx-sticky-module nhưng documentaton nói rằng nếu không có cookie dính nào thì nó sẽ quay trở lại thuật toán Nginx mặc định của vòng tròn - vì vậy nó cũng không giải quyết được vấn đề.

Vì vậy, câu hỏi đặt ra là chúng ta có thể kết hợp logic kết nối ít nhất và ít nhất bằng cách sử dụng Nginx không? Bạn có biết các cân bằng tải khác giải quyết vấn đề này không?

+0

Có lẽ điều này sẽ được chuyển đến serverfault để nhận câu trả lời? – Collector

+0

Câu hỏi thú vị là tại sao "tải trên máy chủ 1 tiếp tục tăng" - có thể là do đa số người dùng của bạn ngồi sau cùng một hoặc một vài NAT? Trong trường hợp này băm trên nguồn IP là không hiệu quả và bạn có thể xem xét sử dụng khóa phức tạp hơn thông qua chỉ thị 'băm' trái với' ip_hash '. Ví dụ: bạn có thể muốn thêm một số phần hoặc tham số URI cụ thể của người dùng vào khóa ... – wick

+0

Câu trả lời hữu ích, nhưng tôi không chắc họ đã trả lời câu hỏi ban đầu. Alex? –

Trả lời

5

Có lẽ bằng cách sử dụng mô-đun split_clients có thể giúp

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; 
} 

này sẽ chia giao thông của bạn và tạo ra các biến $upstreap_app một trong những bạn có thể sử dụng như:

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

Đây là giải pháp cho least_conn và cân bằng tải hoạt động với các phiên dính, "nhược điểm" là nếu cần thêm nhiều máy chủ hơn, cần tạo luồng mới, ví dụ:

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

Để thử nghiệm:

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 

Thông tin thêm về mô-đun này có thể được tìm thấy trong bài viết này (Performing A/B testing)

+0

Lưu ý, 'split_clients' sẽ sử dụng băm đồng nhất để cân bằng tải có thể hoặc không tốt hơn so với round-robin, nhưng KHÔNG phải là những gì op yêu cầu (cân bằng tải dựa trên minimum_conn) – wick

4

Bạn có thể dễ dàng đạt được điều này bằng HAProxy và tôi thực sự đề nghị đi through it thoroughly để xem cách thiết lập hiện tại của bạn có thể có lợi.

Với HA Proxy, bạn muốn có một cái gì đó như:

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 

Mà chỉ đơn giản có nghĩa là proxy được theo dõi các yêu cầu to-and-fro các máy chủ bằng cách sử dụng một cookie.

Tuy nhiên, nếu bạn không muốn sử dụng HAProxy, tôi khuyên bạn nên thiết lập thay đổi triển khai phiên để sử dụng DB trong bộ nhớ như redis/memcached. Bằng cách này, bạn có thể sử dụng lessconn hoặc bất kỳ thuật toán nào khác mà không phải lo lắng về phiên.

Các vấn đề liên quan