2012-07-25 37 views
7

Tình huống của tôi là chúng tôi hiện đang viết một ứng dụng trực tuyến sử dụng Node.js ở phía máy chủ với trình nghe WebSocket. Chúng tôi có hai phần khác nhau: một trang phục vụ các trang và sử dụng node.js và express + ejs, một ứng dụng khác hoàn toàn khác chỉ bao gồm thư viện socket.io cho websockets. Vì vậy, ở đây chúng tôi đi đến vấn đề này của khả năng mở rộng của một phần websockets.Cân bằng tải dựa trên cookie cho WebSockets?

Một giải pháp mà chúng tôi tìm thấy là sử dụng redis và chia sẻ thông tin ổ cắm giữa các máy chủ, nhưng do kiến ​​trúc, nó sẽ yêu cầu chia sẻ nhiều thông tin khác.

Sau phần giới thiệu này, câu hỏi của tôi là - liệu có thể sử dụng cân bằng tải dựa trên cookie cho websockets không? Vì vậy, cho phép nói rằng mọi kết nối từ người dùng với máy chủ cookie = server1 sẽ luôn được chuyển tiếp đến máy chủ1 và mọi kết nối với máy chủ cookie = server2 sẽ được gửi đến máy chủ2 và kết nối không có cookie đó sẽ được chuyển sang máy chủ bận rộn nhất.

CẬP NHẬT: Là một 'câu trả lời' cho biết - có, tôi biết điều này tồn tại. Chỉ cần không nhớ rằng tên là phiên dính. Nhưng câu hỏi là - điều đó có hiệu quả với websockets không? Có bất kỳ biến chứng nào có thể xảy ra không?

+0

Đây là một câu hỏi mà tôi rất quan tâm, chỉ có tôi không thấy vấn đề với các kết nối đến cân bằng tải từ trình duyệt (nó sẽ chỉ nhấn một trong các máy chủ và gắn bó với nó), tôi quan tâm nhiều hơn đến cách bạn thực sự đẩy đến các máy chủ đó từ chương trình phụ trợ của mình. Giống như, tôi có máy chủ phụ trợ thực hiện công việc thực tế và sau đó nó sẽ đẩy thông điệp đến máy chủ websockets thông qua một ổ cắm - làm thế nào để tôi biết cái nào cần đẩy tới nếu tôi có một cụm? Ý tưởng hiện tại của tôi là chỉ giữ danh sách tất cả các kết nối mở ở đâu đó trong db trung tâm, không chắc đó có phải là cách tốt nhất để đi hay không. – KOHb

+0

@KOHb Tôi không có bất kỳ phụ trợ bổ sung nào sau các máy chủ socket. Vì vậy, nó đơn giản hơn nhiều trong trường hợp của tôi. Nhưng từ những gì bạn nói tôi sẽ thử máy chủ Redis cho mục đích này. – AlexKey

Trả lời

5

Chúng tôi gặp sự cố tương tự hiển thị trong ngăn xếp sản xuất Node.js của chúng tôi. Chúng tôi có hai máy chủ sử dụng WebSockets hoạt động cho các trường hợp sử dụng bình thường, nhưng đôi khi trình cân bằng tải sẽ trả lại kết nối này giữa hai máy chủ sẽ gây ra sự cố. (Chúng tôi có mã phiên tại chỗ trên chương trình phụ trợ nên đã sửa nó, nhưng không xử lý đúng cách.)

Chúng tôi đã thử bật Phiên làm việc trên bộ cân bằng tải Barracuda ở phía trước các máy chủ này nhưng thấy rằng nó sẽ chặn WebSocket lưu lượng truy cập do hoạt động của nó. Tôi đã không nghiên cứu chính xác tại sao, vì ít thông tin có sẵn trực tuyến, nhưng có vẻ như điều này là do cách trình cân bằng tách khỏi tiêu đề cho yêu cầu HTTP, lấy cookie và chuyển tiếp yêu cầu đến máy chủ phụ trợ chính xác. Kể từ khi WebSockets bắt đầu như HTTP nhưng sau đó nâng cấp, cân bằng tải đã không nhận thấy sự khác biệt trong kết nối và sẽ cố gắng để làm cùng một xử lý HTTP. Điều này sẽ khiến kết nối WebSocket thất bại, ngắt kết nối người dùng.

Sau đây là những gì chúng tôi hiện có tại chỗ đang hoạt động rất tốt. Chúng tôi vẫn sử dụng cân bằng tải Barracuda ở phía trước máy chủ phụ trợ của chúng tôi, nhưng chúng tôi không có Phiên cố định được bật trên bộ cân bằng tải. Trên các máy chủ phụ trợ của chúng tôi, ở phía trước máy chủ ứng dụng của chúng tôi là HAProxy có hỗ trợ WebSockets đúng cách và có thể cung cấp Phiên cố định theo cách 'bùng binh'.


Danh sách yêu cầu luồng

  1. yêu cầu khách hàng Incoming lượt truy cập chính Barracuda cân bằng tải
  2. cân bằng tải chuyển tiếp cho một trong các máy chủ backend hoạt động
  3. HAProxy nhận được yêu cầu và kiểm tra cho mới 'sticky cookie'
  4. Dựa trên cookie, HAProxy chuyển tiếp đến máy chủ ứng dụng phụ trợ chính xác

Yêu cầu luồng Diagram

WebSocket Request /--> Barracuda 1 -->\ /--> Host 1 -->\ /--> App 1 
------------------->      -->    --> 
        \--> Barracuda 2 -->/ \--> Host 2 -->/ \--> App 1 

Khi các mũi tên quay trở lại một yêu cầu, có nghĩa là yêu cầu có thể chảy vào một trong hai điểm trong dòng chảy.


HAProxy Cấu hình chi tiết

backend app_1 
    cookie ha_app_1 insert 
    server host1 10.0.0.101:80011 weight 1 maxconn 1024 cookie host_1 check 
    server host2 10.0.0.102:80011 weight 1 maxconn 1024 cookie host_2 check 

Trong cấu hình trên:

  • cookie ha_app_1 insert là tên cookie thực tế sử dụng
  • cookie host_1 check hay cookie host_2 check đặt giá trị cookie
+0

Cảm ơn bạn đã trả lời chi tiết này. Nhưng tiếc là chúng tôi vẫn cần phải sử dụng phiên dính rất nhiều cho kết nối ổ cắm. Bạn có proxy đường ống hoặc bạn chuyển hướng nó? – AlexKey

+0

Do phát hiện trong giao thức WebSocket, chúng tôi quyết định gắn bó với giải pháp sau: - kết nối ổ cắm cân bằng tải trên bước handhsake (nó là tốt vì bắt tay chỉ là HTTP) với phiên dính và không phải đường ống proxy, nhưng chuyển hướng nó - Trong trường hợp nếu thay đổi trạng thái - lực kết nối lại máy khách, nơi nó sẽ được cân bằng tải cho máy chủ thích hợp khi bắt tay - các máy chủ được tiếp xúc trong mạng miền phụ (smth như s1-socket.example.com, s2-socket.example.com, v.v.) Nhưng chúng tôi chưa triển khai. Tôi sẽ cập nhật cho bạn khi chúng tôi có nó. – AlexKey

+0

Bình luận đầu tiên của bạn: Chúng tôi vẫn cần sử dụng các phiên cố định, và câu trả lời ở trên là cách chúng tôi triển khai các phiên Sticky theo cách riêng của chúng tôi mà bỏ qua việc sử dụng Phiên tải trọng của Load Balancer. Nhận xét thứ hai của bạn: Điều này nghe có vẻ giống như một kịch bản sẽ phù hợp với bạn. Nó vẫn còn khá giống với chúng ta mặc dù cân bằng tải phần cứng không được sử dụng.Chúng tôi sử dụng HAProxy làm cân bằng tải duy nhất của chúng tôi, cung cấp chức năng cần thiết. –

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