19

Mam aplikację internetową, która nasłuchuje zdarzeń wysłanych na serwer. Kiedy pracowałem i testowałem z kilkoma otwartymi oknami, rzeczy nie działały i kilkakrotnie uderzyłem się w głowę w złym kierunku: w końcu zdałem sobie sprawę, że problemem były równoległe połączenia.Zdarzenia wysyłane przez serwer i limity przeglądarki

Jednak testowałem bardzo ograniczoną liczbę i nawet jeśli jestem uruchomiony test na Apache (wiem, powinienem użyć węzła).

Wówczas przełączyłem przeglądarkę i zauważyłem coś naprawdę interesującego: najwyraźniej Chrome ogranicza połączenia wysyłane przez serwer do 4-5, a Opera nie. Z drugiej strony, Firefox, po 4-5 jednoczesnych połączeniach, odmawia załadowania dowolnej innej strony na inną.

Jaki jest tego powód? Czy limit dotyczy tylko połączeń SSE z tego samego źródła, czy też byłby taki sam, gdybym miał przetestować otwarcie ich z innej domeny? Czy jest jakaś szansa, że ​​źle wykorzystuję SSE, a to faktycznie blokuje przeglądarki, czy jest to znane zachowanie? Czy jest jakiś sposób obejścia tego?

+0

w systemie Windows jest to kontrolowane przez ustawienia rejestru, które IE, chrome i firefox respektują, a które ogranicza wszystkie połączenia, a nie tylko SSE. Miałem ten sam problem z websockets ... nie możesz tego zrobić ... – dandavis

Odpowiedz

26

Sposób, w jaki to działa we wszystkich przeglądarkach, polega na tym, że każda domena ma ograniczoną liczbę połączeń, a limity są globalne dla całej aplikacji. Oznacza to, że jeśli masz otwarte jedno połączenie do komunikacji w czasie rzeczywistym, masz jedno mniej za ładowanie obrazów, css i innych stron. Ponadto nie otrzymujesz nowych połączeń dla nowych kart ani okien, wszystkie muszą udostępniać tę samą liczbę połączeń. Jest to bardzo frustrujące, ale istnieją dobre powody, aby ograniczać połączenia. Kilka lat temu limit ten wynosił 2 we wszystkich przeglądarkach (w oparciu o reguły w (http://www.ietf.org/rfc/rfc2616.txt) specyfikacji HTTP1.1), ale obecnie większość przeglądarek korzysta ogólnie z 4-10 połączeń. Z kolei przeglądarki mobilne wciąż muszą ograniczać ilość połączeń do celów oszczędzania baterii.

te sztuczki są dostępne:

  1. Użyj nazwy bardziej gospodarza. Poprzez przypisanie np. www1.domena.com, www2.domena.com otrzymujesz nowe połączenia dla każdej nazwy hosta. Ta sztuczka działa we wszystkich przeglądarkach. Nie zapomnij zmienić domeny plików cookie, aby uwzględnić całą domenę (domain.com, a nie www.domena.com).
  2. Użyj gniazd internetowych. Gniazda sieciowe nie są ograniczone przez te ograniczenia, a co ważniejsze, nie konkurują z resztą zawartości stron internetowych.
  3. Użyj tego samego połączenia ponownie, gdy otwierasz nowe karty/okna. Jeśli zebrali całą logikę komunikacji w czasie rzeczywistym do koncentratora połączeń obiektu można przypomnieć, że obiekt na wszystkich otwartych okien, takich jak ten:

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

  4. lub używać lampy błyskowej - nie dość najlepsza rada w tych dniach, ale może być jeszcze opcja, jeśli websockets nie są opcją.
  5. Należy pamiętać o dodaniu kilku sekund między każdym poleceniem SSE, aby zezwolić na kolejkowanie żądań przed rozpoczęciem nowego. Dodaj też trochę więcej czasu oczekiwania na każdą sekundę, kiedy użytkownik jest nieaktywny, w ten sposób możesz skoncentrować zasoby serwera na aktywnych użytkownikach.Również dodać liczbę losową z opóźnieniem, aby uniknąć Thundering Herd Problem

Kolejną rzeczą do zapamiętania podczas korzystania wielowątkowe i blokowania języka, takich jak Java czy C# istnieje ryzyko wykorzystania zasobów w swoim wniosku odpytywania długi, które są potrzebne do końca swojego podanie. Na przykład w języku C# każde żądanie blokuje obiekt Session, co oznacza, że ​​cała aplikacja nie odpowiada w czasie, gdy aktywne jest żądanie SSE.

NodeJs doskonale nadaje się do tych celów z wielu powodów, ponieważ już się zorientowałeś i jeśli używasz NodeJS, używałbyś socket.io lub engine.io, który zadba o wszystkie te problemy za pomocą websockets, flashsockets i XHR-polling, a także dlatego, że nie blokuje ani nie łączy pojedynczo, co oznacza, że ​​zużywa bardzo mało zasobów na serwerze, gdy czeka na przesłanie rzeczy. Aplikacja C# zużywa jeden wątek na żądanie oczekujące, które zajmuje co najmniej 2 MB pamięci tylko dla wątku.

+1

Świetna odpowiedź! Czy wiesz, dlaczego Firefox nie chciał otworzyć żadnej innej domeny? – Sunyatasattva

+0

Dzięki; niestety sztuczka window.opener działa tylko dla okien potomnych, które tworzę z mojej aplikacji; nie dla żadnej karty, którą otwiera sam użytkownik. Gdy tylko użytkownik otworzy zbyt wiele zakładek, jestem spieprzony ... Czy wiesz, czy istnieje sposób sprawdzenia, czy niedługo wyczerpiemy wszystkie otwarte połączenia? – phtrivier

+0

Spróbuj użyć (window.parent || window.opener), który zajmie się obu scenariuszy. Zobacz także metodę postMessage do wysyłania wiadomości z zakładkami. Nie sądzę, że istnieje jakikolwiek sposób sprawdzenia ilości połączeń, ale raczej powinieneś raczej użyć właściwości timeout, aby móc reagować na scenariusze, w których żądanie długiego odpytywania blokuje inne żądania. xhr = nowy XMLHttpRequest(); xhr.timeout = 5000; xhr.ontimeout = timeoutFired; –

3

Masz rację co do liczby równoczesnych połączeń.

Można sprawdzić tę listę do wartości max: http://www.browserscope.org/?category=network

I niestety, nie znalazłem żadnej pracy wokół, z wyjątkiem multipleksowanie i/lub przy użyciu różnych hostów.

Powiązane problemy