Czy HTML WebSockets utrzymuje otwarte połączenie dla każdego klienta? Czy to skala?

159

Ciekawe, czy ktoś ma jakieś informacje o skalowalności HTML WebSockets. Z wszystkiego, co przeczytałem, wynika, że ​​każdy klient będzie utrzymywał otwartą linię komunikacji z serwerem. Zastanawiam się tylko, jak to się skaluje i ile otwartych połączeń WebSocket może obsłużyć serwer. Może pozostawienie otwartych połączeń nie stanowi w rzeczywistości problemu, ale wydaje się, że tak jest.

Ryan Montgomery
źródło
1
Nie ma czegoś takiego jak HTML WebSocket. Masz na myśli HTTP WebSocket.
Markiz Lorne

Odpowiedzi:

209

W większości przypadków WebSockets będzie prawdopodobnie lepiej skalować niż żądania AJAX / HTML. Nie oznacza to jednak, że WebSockets jest zamiennikiem wszystkich zastosowań AJAX / HTML.

Każde połączenie TCP samo w sobie zużywa bardzo mało zasobów serwera. Często ustanowienie połączenia może być kosztowne, ale utrzymanie bezczynnego połączenia jest prawie bezpłatne. Pierwszym zwykle napotykanym ograniczeniem jest maksymalna liczba deskryptorów plików (gniazda wykorzystują deskryptory plików), które mogą być jednocześnie otwarte. Często jest to wartość domyślna 1024, ale można ją łatwo skonfigurować wyżej.

Czy próbowałeś kiedyś skonfigurować serwer WWW do obsługi dziesiątek tysięcy jednoczesnych klientów AJAX? Zmień tych klientów w klientów WebSockets, a może to być wykonalne.

Połączenia HTTP, chociaż nie tworzą otwartych plików ani nie zużywają numerów portów przez długi czas, są droższe w prawie każdym innym przypadku:

  • Każde połączenie HTTP niesie ze sobą dużo bagażu, który nie jest używany przez większość czasu: pliki cookie, typ zawartości, długość kontekstu, agent użytkownika, identyfikator serwera, data, ostatnia modyfikacja itp. Po ustanowieniu połączenia WebSockets tylko dane wymagane przez aplikację muszą być przesyłane tam iz powrotem.

  • Zazwyczaj serwery HTTP są skonfigurowane tak, aby rejestrować rozpoczęcie i zakończenie każdego żądania HTTP zajmującego dysk i czas procesora. Rejestrowanie początku i końca danych WebSockets stanie się standardem, ale podczas gdy połączenie WebSockets wykonuje transfer dwustronny, nie będzie żadnego dodatkowego narzutu rejestrowania (z wyjątkiem aplikacji / usługi, jeśli jest do tego zaprojektowana).

  • Zazwyczaj aplikacje interaktywne korzystające z technologii AJAX albo stale sondują, albo używają jakiegoś mechanizmu długiego odpytywania. WebSockets to znacznie czystszy (i mniej zasobny) sposób tworzenia modelu opartego na większej liczbie zdarzeń, w którym serwer i klient powiadamiają się nawzajem, gdy mają coś do zgłoszenia w ramach istniejącego połączenia.

  • Większość popularnych serwerów WWW w produkcji ma pulę procesów (lub wątków) do obsługi żądań HTTP. Wraz ze wzrostem ciśnienia wielkość puli zostanie zwiększona, ponieważ każdy proces / wątek obsługuje jednocześnie jedno żądanie HTTP. Każdy dodatkowy proces / wątek zużywa więcej pamięci, a tworzenie nowych procesów / wątków jest nieco droższe niż tworzenie nowych połączeń gniazd (które te procesy / wątki nadal muszą wykonywać). Większość popularnych platform serwerowych WebSockets korzysta z trasy zdarzeniowej, która ma tendencję do skalowania i lepszej wydajności.

Podstawową zaletą WebSockets będą mniejsze opóźnienia połączeń dla interaktywnych aplikacji internetowych. Będzie lepiej skalować i zużywać mniej zasobów serwera niż HTTP AJAX / long-poll (zakładając, że aplikacja / serwer jest prawidłowo zaprojektowana), ale mniejsze opóźnienie IMO jest główną zaletą WebSockets, ponieważ umożliwi nowe klasy aplikacji internetowych, które nie są możliwe z bieżącym narzutem i opóźnieniem AJAX / long-poll.

Gdy standard WebSockets będzie bardziej sfinalizowany i będzie miał szersze wsparcie, sensowne będzie używanie go w przypadku większości nowych interaktywnych aplikacji internetowych, które muszą często komunikować się z serwerem. W przypadku istniejących interaktywnych aplikacji internetowych będzie to naprawdę zależeć od tego, jak dobrze działa obecny model AJAX / długich ankiet. Wysiłek związany z konwersją będzie nietrywialny, więc w wielu przypadkach koszt po prostu nie będzie wart korzyści.

Aktualizacja :

Przydatny link: 600 tys. Jednoczesnych połączeń internetowych w AWS przy użyciu Node.js.

kanaka
źródło
4
Niesamowity anser. Dziękuję za poświęcenie czasu na odpowiedź.
Ryan Montgomery,
7
Jednak nadal nie wiem, jak skalować po uderzeniu w ścianę. To prawda, że ​​WebSockets zużywają mniej zasobów (skalują się w pionie), ale HTTP świetnie nadaje się do skalowania w poziomie. Teoretycznie mogę dodawać serwery, aby skalować w nieskończoność. Zawsze byłem zdezorientowany, jak skalować, gdy wykorzystasz pojemność jednego pudełka. Myśli?
Sean Clark Hess
6
@Sean. WebSockets niekoniecznie jest gorsze w skalowaniu w poziomie. Po prostu otwiera nowe aplikacje, które niekoniecznie są tak łatwe do skalowania. Na przykład do obsługi danych statycznych grupa serwerów WebSocket skaluje się równie dobrze (lub lepiej) niż grupa serwerów HTTP. Gra czasu rzeczywistego o małych opóźnieniach jest trudna do skalowania niezależnie od transportu (i po prostu nie jest to wykonalne przy użyciu protokołu HTTP). Prawdziwe pytanie brzmi, jak dobrze skalujesz dane / aplikacje. Jeśli to skalach, to twój wybór HTTP vs WebSocket powinna opierać się na innych czynnikach: latencji, opcji wdrożeniowych, wsparcie przeglądarki, itp
kanaka
2
Jedna poprawka - połączenie TCP składa się z docelowego adresu IP i portu docelowego. Oznacza to, że limit portów ± 64 tys. Faktycznie dotyczy TYLKO jednego klienta. Teoretycznie serwer może mieć dowolną liczbę otwartych połączeń, ograniczonych TYLKO przez jego sprzęt.
Rizon,
@Rizon, to prawda. Zaktualizowałem odpowiedź i zmieniłem ograniczenie otwartego portu, a zamiast tego wspomniałem o ograniczeniu deskryptora pliku, z którym ludzie często spotykają się jako pierwsi.
kanaka
36

Tylko wyjaśnienie: liczba połączeń klientów, które może obsługiwać serwer, nie ma nic wspólnego z portami w tym scenariuszu, ponieważ serwer [zwykle] nasłuchuje tylko połączeń WS / WSS na jednym porcie. Myślę, że inni komentatorzy mieli na myśli deskryptory plików. Możesz ustawić maksymalną liczbę deskryptorów plików na dość wysoką, ale wtedy musisz uważać na sumowanie się rozmiarów buforów gniazda dla każdego otwartego gniazda TCP / IP. Tutaj jest kilka dodatkowych informacji: /server/48717/practical-maximum-open-file-descriptors-ulimit-n-for-a-high-volume-system

Jeśli chodzi o zmniejszone opóźnienie przez WS w porównaniu z HTTP, to prawda, ponieważ nie ma już analizowania nagłówków HTTP poza początkowym uzgadnianiem WS. Ponadto wraz z pomyślnym wysyłaniem coraz większej liczby pakietów okno przeciążenia TCP rozszerza się, skutecznie zmniejszając czas RTT.

Michael
źródło
AFAIR jest jeden port przychodzący, ale zawsze jeden port wychodzący otwarty dla każdego połączenia. W rzeczywistości jest to tylko jedna część problemu C10k .
Arnaud Bouchez
14

Każdy nowoczesny serwer jest w stanie obsłużyć jednocześnie tysiące klientów . Jego oprogramowanie serwera HTTP musi być po prostu zorientowane na zdarzenia (IOCP) (nie jesteśmy już w starym Apache jedno połączenie = jedno równanie wątku / procesu). Nawet serwer HTTP wbudowany w Windows (http.sys) jest zorientowany na IOCP i bardzo wydajny (działa w trybie jądra). Z tego punktu widzenia nie będzie dużej różnicy w skalowaniu między WebSockets a zwykłym połączeniem HTTP. Jedno połączenie TCP / IP zużywa trochę zasobów (znacznie mniej niż wątek), a nowoczesny system operacyjny jest zoptymalizowany do obsługi wielu równoczesnych połączeń: WebSockets i HTTP to tylko protokoły warstwy aplikacji OSI 7, dziedziczące po specyfikacjach TCP / IP.

Ale z eksperymentu widziałem dwa główne problemy z WebSockets:

  1. Nie obsługują CDN;
  2. Mają potencjalne problemy z bezpieczeństwem.

Dlatego dla każdego projektu polecam:

  • Używaj WebSockets tylko do powiadomień klientów (z mechanizmem awaryjnym do długiego sondowania - w pobliżu jest mnóstwo bibliotek);
  • Użyj RESTful / JSON dla wszystkich innych danych, używając CDN lub serwerów proxy do pamięci podręcznej.

W praktyce pełne aplikacje WebSockets nie skalują się dobrze. Po prostu używaj WebSockets do tego, do czego zostały zaprojektowane: powiadomienia push z serwera do klienta.

O potencjalnych problemach związanych z używaniem WebSockets:

1. Rozważ użycie CDN

Obecnie (prawie 4 lata później) skalowanie sieci Web obejmuje korzystanie z interfejsów sieci dostarczania treści (CDN), nie tylko w przypadku zawartości statycznej (html, css, js), ale także danych aplikacji (JSON) .

Oczywiście nie umieścisz wszystkich danych w pamięci podręcznej CDN, ale w praktyce wiele typowych treści nie będzie się często zmieniać. Podejrzewam, że 80% zasobów REST może być zapisanych w pamięci podręcznej ... Nawet minuta (lub 30 sekund) wygaśnięcia CDN może wystarczyć, aby dać serwerowi centralnemu nowe życie i znacznie poprawić responsywność aplikacji, ponieważ CDN może być dostosowanym geograficznie ...

O ile mi wiadomo, w CDN nie ma jeszcze obsługi WebSockets i podejrzewam, że nigdy by tak nie było. WebSockets są pełne, podczas gdy HTTP jest bezstanowe, więc można je łatwo buforować. W rzeczywistości, aby usługa WebSockets była przyjazna dla CDN, może być konieczne przełączenie się na bezstanowe podejście RESTful ... które nie byłoby już WebSockets.

2. Kwestie bezpieczeństwa

WebSockets mają potencjalne problemy z bezpieczeństwem, szczególnie w przypadku ataków DOS. Aby zapoznać się z nowymi lukami w zabezpieczeniach, zobacz ten zestaw slajdów i ten bilet do zestawu internetowego .

WebSockets unikają jakiejkolwiek szansy na kontrolę pakietów na poziomie warstwy aplikacji OSI 7, która jest obecnie dość standardem w każdym zabezpieczeniu biznesowym. W rzeczywistości WebSockets sprawia, że ​​transmisja jest zaciemniona, więc może to być poważne naruszenie bezpieczeństwa.

Arnaud Bouchez
źródło
2
@ArnaudBouchez - +1 za ładną ekspozycję na CDN. Szybkie pytanie uzupełniające - co sądzisz o wykonalności sieci dostarczania wydarzeń? Wzorowany na CDN, ale ukierunkowany na dostarczanie danych strumieniowych itp. Za pośrednictwem gniazd internetowych lub innej niewidzianej jeszcze technologii.
quixver
8

Pomyśl o tym w ten sposób: co jest tańsze, utrzymywanie otwartego połączenia lub otwieranie nowego połączenia dla każdego żądania (z kosztami negocjacji, pamiętaj, że jest to TCP).

Oczywiście zależy to od aplikacji, ale w przypadku długoterminowych połączeń w czasie rzeczywistym (np. Czat AJAX) znacznie lepiej jest pozostawić otwarte połączenie.

Maksymalna liczba połączeń zostanie ograniczona przez maksymalną liczbę wolnych portów dla gniazd.

kaoD
źródło
Możesz pozostawić otwarte połączenie bez użycia WebSocket (dzięki opcji utrzymywania aktywności HTTP / 1.1). Nie jestem pewien, czy rozumiem twój punkt widzenia.
Arnaud Bouchez
1
+1. Ludzie często zapominają, że ustanowienie połączenia TCP obejmuje synchronizację / potwierdzenie / potwierdzenie, a protokół TLS wymaga więcej podróży w obie strony przy wymianie kluczy.
quixver,
1
@ArnaudBouchez check en.wikipedia.org/wiki/HTTP_persistent_connection#HTTP_1.1 WebSockets są otwarte tak długo, jak chcesz i nie są hackerskie (jak długie odpytywanie i inne alternatywy).
kaoD
-5

Nie, nie skaluje się, daje ogromną pracę przełącznikom tras pośrednich. Wtedy po stronie serwera błędy strony (musisz zachować wszystkie te deskryptory) osiągają wysokie wartości, a czas na wprowadzenie zasobu do obszaru roboczego wydłuża się. Są to głównie serwery napisane w języku JAVA i może być szybciej trzymać te gaziliony gniazd niż je zniszczyć / utworzyć. Gdy uruchamiasz taki serwer na maszynie, żaden inny proces nie może się już przenieść.

user2195463
źródło