19

Tôi có ứng dụng web lắng nghe Sự kiện được gửi trên máy chủ. Trong khi tôi đang làm việc và thử nghiệm với nhiều cửa sổ đang mở, mọi thứ đã không hoạt động và tôi đã đập đầu mình nhiều lần nhìn sai hướng: cuối cùng, tôi nhận ra rằng vấn đề là kết nối đồng thời.Máy chủ đã gửi sự kiện và giới hạn trình duyệt

Tuy nhiên tôi đã thử nghiệm một số rất hạn chế và ngay cả khi tôi đang chạy thử nghiệm trên Apache (tôi biết, tôi nên sử dụng nút).

Sau đó, tôi đã chuyển trình duyệt và nhận thấy điều gì đó thực sự thú vị: rõ ràng Chrome giới hạn sự kiện Máy chủ đã gửi kết nối đến 4-5, trong khi Opera thì không. Firefox, mặt khác, sau 4-5 kết nối đồng thời, từ chối tải bất kỳ trang nào khác.

Lý do đằng sau điều này là gì? Liệu giới hạn chỉ áp dụng cho các kết nối SSE từ cùng một nguồn, hoặc nó sẽ giống nhau nếu tôi thử mở chúng từ một miền khác? Có bất kỳ cơ hội nào mà tôi đang lạm dụng SSE và điều này thực sự đang chặn các trình duyệt hay đây là hành vi đã biết? Có cách nào xung quanh nó không?

+0

trong cửa sổ, điều này được kiểm soát bởi cài đặt đăng ký mà IE, chrome và firefox tôn trọng và giới hạn tất cả các kết nối, không chỉ SSE. Tôi đã có cùng một vấn đề với websockets ... bạn không thể làm điều này lên ... – dandavis

Trả lời

26

Cách hoạt động trong tất cả các trình duyệt là mỗi miền nhận được số lượng kết nối giới hạn và giới hạn là toàn cầu cho toàn bộ ứng dụng của bạn. Điều đó có nghĩa là nếu bạn có một kết nối mở cho giao tiếp thời gian thực, bạn có một ít hơn để tải hình ảnh, css và các trang khác. Trên hết, bạn không nhận được kết nối mới cho các tab hoặc cửa sổ mới, tất cả chúng cần chia sẻ cùng một lượng kết nối. Điều này là rất bực bội nhưng có những lý do tốt để hạn chế các kết nối. Một vài năm trở lại, giới hạn này là 2 trong tất cả các trình duyệt (dựa trên các quy tắc trong (http://www.ietf.org/rfc/rfc2616.txt) HTTP1.1 spec) nhưng bây giờ hầu hết các trình duyệt sử dụng 4-10 kết nối nói chung. Mặt khác, các trình duyệt di động vẫn cần giới hạn số lượng kết nối cho mục đích tiết kiệm pin.

Những thủ thuật có sẵn:

  1. Sử dụng tên nhiều máy chủ. Bằng cách chỉ định cũ. www1.domain.com, www2.domain.com bạn nhận được kết nối mới cho mỗi tên máy chủ. Thủ thuật này hoạt động trong tất cả các trình duyệt. Đừng quên thay đổi tên miền cookie để bao gồm toàn bộ miền (domain.com, không phải www.domain.com)
  2. Sử dụng ổ cắm web. Web socket không bị giới hạn bởi những hạn chế này và quan trọng hơn là chúng không cạnh tranh với phần còn lại của nội dung trang web của bạn.
  3. Sử dụng lại cùng một kết nối khi bạn mở tab/cửa sổ mới. Nếu bạn đã thu thập tất cả các logic giao tiếp thời gian thực đến một Hub gọi đối tượng bạn có thể gọi lại đối tượng đó trên tất cả các cửa sổ đang mở như thế này:

    window.hub = window.opener ? window.opener.hub || new Hub()

  4. hoặc sử dụng flash - không hẳn là lời khuyên tốt nhất những ngày này nhưng nó vẫn có thể một tùy chọn nếu websockets không phải là một tùy chọn.
  5. Hãy nhớ thêm vài giây thời gian giữa mỗi yêu cầu SSE để yêu cầu xóa hàng đợi trước khi bắt đầu một yêu cầu mới. Ngoài ra, thêm một chút thời gian chờ đợi cho mỗi giây người dùng không hoạt động, theo cách đó bạn có thể tập trung tài nguyên máy chủ của mình vào những người dùng đang hoạt động.Ngoài ra thêm một số ngẫu nhiên của sự chậm trễ để tránh Thundering Herd Problem

Một điều cần nhớ khi sử dụng một ngôn ngữ đa luồng và chặn như Java hay C# bạn có nguy cơ sử dụng tài nguyên trong yêu cầu bỏ phiếu dài của bạn mà là cần thiết cho phần còn lại của bạn ứng dụng. Ví dụ trong C# mỗi yêu cầu khóa đối tượng Session có nghĩa là toàn bộ ứng dụng không phản hồi trong thời gian yêu cầu SSE đang hoạt động.

NodeJs là lựa chọn tuyệt vời cho nhiều lý do như bạn đã biết và nếu bạn đang sử dụng NodeJS, bạn đã sử dụng socket.io hoặc engine.io để xử lý tất cả các sự cố này bằng cách sử dụng ổ cắm web, ổ cắm flash và XHR-polling và cũng bởi vì nó không bị chặn và đơn luồng có nghĩa là nó sẽ tiêu tốn rất ít tài nguyên trên máy chủ khi nó chờ đợi những thứ để gửi. Một ứng dụng C# tiêu thụ một luồng cho mỗi yêu cầu chờ đợi có ít nhất 2MB bộ nhớ chỉ dành cho chuỗi.

+1

Câu trả lời tuyệt vời! Bạn có biết tại sao Firefox từ chối mở bất kỳ tên miền nào khác không? – Sunyatasattva

+0

Cảm ơn; không may, mẹo window.opener sẽ chỉ hoạt động đối với các cửa sổ con mà tôi tạo từ ứng dụng của mình; không cho bất kỳ tab nào mà người dùng tự mở. Ngay sau khi người dùng mở quá nhiều tab, tôi đang say ... Bạn có biết có cách nào để kiểm tra xem chúng tôi sắp hết tất cả các kết nối chưa? – phtrivier

+0

Hãy thử sử dụng (window.parent || window.opener) sẽ xử lý cả hai trường hợp. Ngoài ra, hãy xem phương thức postMessage để gửi các thông điệp thẻ chéo. Tôi không nghĩ rằng có bất kỳ cách nào để thấy số lượng kết nối nhưng bạn nên sử dụng thuộc tính thời gian chờ để có thể phản ứng với các tình huống mà yêu cầu bỏ phiếu dài đang trì hoãn các yêu cầu khác. xhr = new XMLHttpRequest(); xhr.timeout = 5000; xhr.ontimeout = timeoutFired; –

3

Bạn đúng về số lượng kết nối đồng thời.

Bạn có thể kiểm tra danh sách này cho các giá trị tối đa: http://www.browserscope.org/?category=network

Và thật không may, tôi không bao giờ tìm thấy bất kỳ việc xung quanh, ngoại trừ ghép kênh và/hoặc sử dụng hostname khác nhau.

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