WebSockets vs. Zdarzenia wysłane przez serwer / EventSource

838

Zarówno WebSockets, jak i zdarzenia wysyłane przez serwer są w stanie przesyłać dane do przeglądarek. Wydaje mi się, że są to konkurujące technologie. Jaka jest różnica między nimi? Kiedy wybierzesz jedną z drugiej?

Mads Mobæk
źródło
2
Nie jestem pewien, jak postrzegasz ich jako konkurencyjnych. Jeden jest synchroniczny i mógłby / mógłby zostać wykorzystany do przesyłania danych w czasie zbliżonym do czasu rzeczywistego, podczas gdy drugi jest asynchroniczny i służyłby zupełnie innemu celowi (efektywne wysyłanie wiadomości typu toast z aplikacji po stronie serwera).
Brian Driscoll,
54
WebSockets jest dwukierunkowy, może wysyłać dane do serwera.
Andre Backlund,
13
Jedną z rzeczy, które naprawdę lubię w SSE, jest to, że łatwo jest je rozwiązywać ... wystarczy otworzyć żądanie na serwerze SSE curl. Ponieważ jest to tylko format tekstowy przez HTTP, łatwo jest zobaczyć, co się dzieje.
Sam
7
@BrianDriscoll - asynchroniczny / synchroniczny - który jest który? O ile rozumiem oba włączyć transfery asynchroniczne?
Dave Everitt,
5
SSE nie działa na IE, działa websockets
Tyler Gillies

Odpowiedzi:

977

Zarówno Websockets, jak i SSE (Server Sent Events) są w stanie przesyłać dane do przeglądarek, jednak nie są to konkurencyjne technologie.

Połączenia Websockets mogą zarówno wysyłać dane do przeglądarki, jak i odbierać dane z przeglądarki. Dobrym przykładem aplikacji, która mogłaby korzystać z websockets, jest aplikacja do czatu.

Połączenia SSE mogą przekazywać dane tylko do przeglądarki. Notowania giełdowe online lub Twitter aktualizujący oś czasu lub kanał to dobre przykłady aplikacji, która mogłaby skorzystać z SSE.

W praktyce, ponieważ wszystko, co można zrobić za pomocą SSE, można również zrobić za pomocą Websockets, Websockets zyskuje o wiele więcej uwagi i miłości, a wiele innych przeglądarek obsługuje Websockets niż SSE.

Jednak w przypadku niektórych typów aplikacji może to być nadmiar, a backend może być łatwiejszy do wdrożenia przy pomocy protokołu takiego jak SSE.

Ponadto SSE może być wypełniane w starszych przeglądarkach, które nie obsługują go natywnie za pomocą samego JavaScript. Niektóre implementacje wypełnień SSE można znaleźć na stronie github Modernizr .

Gotchas:

  • SSE cierpi z powodu ograniczenia maksymalnej liczby otwartych połączeń, co może być szczególnie bolesne przy otwieraniu różnych kart, ponieważ limit dotyczy przeglądarki i jest ustawiony na bardzo niską liczbę (6). Problem został oznaczony jako „Nie naprawi” w Chrome i Firefox . Limit ten dotyczy przeglądarki + domeny, co oznacza, że ​​możesz otworzyć 6 połączeń SSE na wszystkich kartach www.example1.comi kolejne 6 połączeń SSE do www.example2.com(dzięki Phate).
  • Tylko WS może przesyłać zarówno dane binarne, jak i UTF-8, SSE jest ograniczone do UTF-8. (Dzięki Chado Nihi).
  • Niektóre zapory ogniowe z inspekcją pakietów mają problemy z obsługą WebSockets (Sophos XG Firewall, WatchGuard, McAfee Web Gateway).

HTML5Rocks ma kilka dobrych informacji na temat SSE. Z tej strony:

Zdarzenia wysłane przez serwer a WebSockets

Dlaczego wybrałeś zdarzenia wysyłane przez serwer zamiast WebSockets? Dobre pytanie.

Jednym z powodów, dla których SSE były trzymane w cieniu, jest fakt, że późniejsze interfejsy API, takie jak WebSockets, zapewniają bogatszy protokół umożliwiający dwukierunkową komunikację w pełnym dupleksie. Posiadanie dwukierunkowego kanału jest bardziej atrakcyjne w przypadku gier, aplikacji do przesyłania wiadomości oraz przypadków, w których potrzebujesz aktualizacji w czasie rzeczywistym w obu kierunkach. Jednak w niektórych scenariuszach dane nie muszą być wysyłane od klienta. Potrzebujesz tylko aktualizacji z niektórych działań serwera. Kilka przykładów to aktualizacje statusu znajomych, notowania giełdowe, kanały informacyjne lub inne automatyczne mechanizmy wypychania danych (np. Aktualizacja bazy danych SQL Web po stronie klienta lub składnicy obiektów IndexedDB). Jeśli będziesz musiał wysłać dane do serwera, XMLHttpRequest jest zawsze przyjacielem.

SSE są przesyłane tradycyjnym HTTP. Oznacza to, że do działania nie wymagają specjalnego protokołu ani implementacji serwera. Z drugiej strony WebSockets wymagają połączenia pełnego dupleksu i nowych serwerów Web Socket do obsługi protokołu. Ponadto zdarzenia wysyłane przez serwer mają wiele funkcji, których WebSockets brakuje z założenia, takich jak automatyczne ponowne łączenie, identyfikatory zdarzeń i możliwość wysyłania dowolnych zdarzeń.


Podsumowanie TLDR:

Zalety SSE nad Websockets:

  • Transportowany przez prosty HTTP zamiast niestandardowego protokołu
  • Może być wielokrotnie wypełniany javascript do „backportowania” SSE do przeglądarek, które jeszcze go nie obsługują.
  • Wbudowana obsługa ponownego połączenia i identyfikatora zdarzenia
  • Prostszy protokół
  • Nie ma problemu z korporacyjnymi zaporami ogniowymi wykonującymi kontrolę pakietów

Zalety Websockets nad SSE:

  • Komunikacja w czasie rzeczywistym, dwukierunkowa.
  • Natywne wsparcie w większej liczbie przeglądarek

Idealne przypadki użycia SSE:

  • Akcje giełdowe giełdowe
  • aktualizacja kanału Twitter
  • Powiadomienia dla przeglądarki

Gotówki SSE:

  • Brak wsparcia binarnego
  • Maksymalny limit otwartych połączeń
Alex Recarey
źródło
131
Czat jest doskonale wykonalny dzięki SSE - możesz używać zwykłego testu POST do wysyłania wiadomości na serwer. WebSockets byłyby potrzebne tylko wtedy, gdy wdrażasz chat a'la Google Wave.
Kornel
135
Prawdą jest, że czat i inne aplikacje w czasie rzeczywistym można wykonywać za pomocą SSE. Wymaga to jednak odpowiedzi POST „poza pasmem”, tzn. Nie jest to kontrolowane przez protokół SSE i nie wydaje się dobrym przykładem podstawowego wyjaśnienia różnic między SSE a Websockets. Możesz wdrożyć czat z podstawowym HTTP odpytywaniem serwera co sekundę i wysyłaniem nowych odpowiedzi. Nie oznacza to, że jest to najlepszy / najbardziej elegancki sposób na zrobienie tego.
Alex Recarey,
14
Myślę, że rozwiązanie pomeL jest świetnym kompromisem w większości przypadków, ponieważ JS zawsze może „wypchnąć” rzeczy na serwer za pomocą AJAX POST. Z mojego doświadczenia wynika, że ​​głównym problemem była potrzeba sondowania przez JS nowych informacji, ale SSE dba o to. : D
Jacob Pritchett
12
@MattDiPasquale Wave wysłał każdy klucz indywidualnie podczas wpisywania zamiast pełnej wiadomości na raz. 200 bajtów narzutu POST dla 1 naciśnięcia klawisza byłoby marnotrawstwem w porównaniu do około 6 dla WebSocket.
Kornel,
9
Wydaje się trochę dziwne stwierdzenie, że nie są to konkurujące technologie, a następnie opisać, że można je wykorzystać do osiągnięcia podobnych rozwiązań. Powiedziałbym, że to sprawia, że ​​konkurują.
Alex,
115

Według caniuse.com:

Możesz użyć polifill tylko dla klienta, aby rozszerzyć obsługę SSE na wiele innych przeglądarek. Jest to mniej prawdopodobne w przypadku WebSockets. Niektóre wypełniacze EventSource:

  • EventSource autorstwa Remy Sharp bez żadnych innych zależności bibliotecznych (IE7 +)
  • jQuery.EventSource autor: Rick Waldron
  • EventSource by Yaffle (zastępuje natywną implementację, normalizuje zachowanie w różnych przeglądarkach)

Jeśli potrzebujesz obsługiwać wszystkie przeglądarki, rozważ użycie biblioteki takiej jak web-socket-js , SignalR lub socket.io, która obsługuje wiele transportów, takich jak WebSockets, SSE, Forever Frame i długie odpytywanie AJAX. Często wymagają one również modyfikacji po stronie serwera.

Dowiedz się więcej o SSE od:

Dowiedz się więcej o WebSockets od:

Inne różnice:

  • WebSockets obsługuje dowolne dane binarne, SSE używa tylko UTF-8
Drew Noakes
źródło
3
Chciałbym podkreślić, że w 2016 r.> 95% globalnych użytkowników natywnie wspiera WebSockets. Wszystkie przeglądarki i urządzenia obsługują WebSockets od ponad 4 lat. Socket.IO powróci do długiego odpytywania AJAX i poradzi sobie ze złożonością emulacji WebSockets, jeśli nie jest obsługiwane, co zapewnia obsługę w 100%. Jeśli używasz czegokolwiek poza WebSockets w 2016 roku, używasz przestarzałej technologii.
Nick Steele,
3
@NickSteele To jest hype bzdura. Poleganie na starszych standardach jest całkowicie w porządku, jeśli spełniają one twój przypadek użycia i nie oznacza, że ​​wszystko jest przestarzałe. To po prostu inny standard. Np .: XHR wciąż może robić wiele rzeczy, których nie potrafi API Fetch, więc nie jest przestarzały. To jest inne. W przeszłości korzystałem z WS, ale z doświadczenia wiem, że można napotkać przeszkody w postaci szumów zapory korporacyjnej, która blokuje żądania, gdy nie rozumie WS. SSE jest super wydajne pod względem tego, co robi, jest banalnie zrozumiałe, możliwe do wdrożenia i łatwe do debugowania. Dla naszego jednokierunkowego przepływu danych jest idealny.
oligofren,
@oligofren Nie trzeba przeklinać. Jeśli coś ma zastąpić poprzednią wersję, a jest to przyjęte w branży i lepsze pod każdym względem, z definicji stara metoda jest przestarzała. Podobnie jak oryginalny iPhone jest przestarzały, podobnie jak XHR. XHR pojawiło się przed Firefox, Chrome, pierwszym iPhone'em, przed YouTube, Netflix, Facebook, a nawet MySpace. Kiedy pojawił się XHR, Windows 98 był najlepszym systemem operacyjnym, AOL był najlepszym dostawcą, a JSON nawet nie istniał. WebSockets zastąpił XHR prawie dziesięć lat temu. Jeśli trafisz w zaczepy za pomocą WS, to, co spowodowało zaczep, jest również nieaktualne. Nie ma usprawiedliwienia dla tak daleko w tyle.
Nick Steele,
4
Zastąp więc BS hiperbolą :-) WS nie zastępuje XHR / HTTP bardziej niż drony do samochodów dostawczych. To różne przypadki użycia. WS nie jest HTTP i ma różne słodkie punkty. Jeśli spróbujesz, skończysz na ponownym wdrażaniu HTTP (słabo) w przestrzeni użytkownika. Sugerujesz także rzeczy, które nie są podane do wiadomości: WS jest po prostu dwukierunkowym protokołem wspierającym push serwera. Nigdy nie widziałem, aby jakiekolwiek dokumenty projektowe wspominały, że są opracowywane jako zamiennik czegokolwiek. Źródło? Wiek sam w sobie nie jest czynnikiem. Po wybraniu opcji wybierz najprostszą implementację, sprawdzając wszystkie wymagania.
oligofren,
1
Zaledwie dwa lata temu (2017) debugowałem zrzuty sterty procesów Node JS, w których kod Socket.io powodował ogromne rozdrobnienie pamięci w procesie IIS, kończąc rozmowę bezpośrednio z zespołem Azure Node. Całkowita złożoność nie jest za darmo. Jeśli potrafisz uciec od prostego skryptu 20-liniowego jako swojej zależności od serwera, a mimo to nadal być w stanie obsłużyć 100 000 klientów, wybrałbym to. Uwielbiam WS za to, co robi, ale przed wybraniem rozwiązania spójrz na to, czego potrzebujesz.
oligofren
16

Opera, Chrome, Safari obsługuje SSE, Chrome, Safari obsługuje SSE wewnątrz SharedWorker Firefox obsługuje XMLHttpRequest readyState Interactive, dzięki czemu możemy uczynić EventSource polyfil dla Firefox

Yaffle
źródło
8

Websocket VS SSE


Gniazda sieciowe - jest to protokół, który zapewnia pełny dupleksowy kanał komunikacyjny za pośrednictwem jednego połączenia TCP. Na przykład dwukierunkowa komunikacja między serwerem a przeglądarką Ponieważ protokół jest bardziej skomplikowany, serwer i przeglądarka muszą polegać na bibliotece websocket, która jestsocket.io

Example - Online chat application.

SSE (Zdarzenie wysłane przez serwer ) - W przypadku zdarzenia wysłanego przez serwer komunikacja odbywa się tylko z serwera do przeglądarki, a przeglądarka nie może wysłać żadnych danych do serwera. Ten rodzaj komunikacji jest używany głównie wtedy, gdy konieczne jest jedynie pokazanie zaktualizowanych danych, a następnie serwer wysyła komunikat za każdym razem, gdy dane są aktualizowane. Na przykład jednokierunkowa komunikacja między serwerem a przeglądarką. Ten protokół jest mniej skomplikowany, więc nie trzeba polegać na zewnętrznej bibliotece, która sama JAVASCRIPT zapewnia EventSourceinterfejs do odbierania wysyłanych przez serwer wiadomości.

Example - Online stock quotes or cricket score website.
Gaurav Tiwari
źródło
4

Należy zwrócić uwagę na jedną rzecz:
miałem problemy z gniazdami sieciowymi i zaporami korporacyjnymi. (Korzystanie z HTTPS pomaga, ale nie zawsze).

Zobacz https://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software https://github.com/sockjs/sockjs-client/issues/94

I zakładamy, że nie ma tyle problemów z serwera Sent Events. Ale nie wiem.

To powiedziawszy, WebSockets to mnóstwo zabawy. Mam małą grę internetową, która korzysta z websockets (przez Socket.IO) ( http://minibman.com )

Drew LeSueur
źródło
1
Miałem również problemy z zaporami korporacyjnymi.
oligofren,
1
Jednym ze problemów, które widziałem w przypadku zdarzeń wysyłanych przez serwer, jest to, że niektóre proxy / zapory mogą go blokować, ponieważ nie ma nagłówka Content-Length
Drew LeSueur
2

Oto omówienie różnic między gniazdami sieciowymi a zdarzeniami wysyłanymi przez serwer. Od wersji Java EE 7 interfejs API WebSocket jest już częścią specyfikacji i wygląda na to, że zdarzenia wysyłane przez serwer zostaną wydane w następnej wersji wersji Enterprise.

Patrick Leitermann
źródło
-3

Maksymalny limit połączeń nie stanowi problemu w przypadku http2 + sse.

To był problem na http 1

użytkownik1948585
źródło
Http2 pozwala na traktowanie wielu żądań w tej samej domenie jako strumieni. Ta technika nazywa się multipleksowaniem. Oszczędza to limity połączeń przeglądarki na domenę, co jest powodem, dla którego ludzie dzielą domeny na HTTP za pomocą Http1.
user1948585
1
Strumienie HTTP / 2 są również ograniczone, co chroni serwery przed bombardowaniem przez jedną przeglądarkę i zmusza przeglądarki do ograniczenia ich multipleksowania do ograniczonej liczby strumieni - co w naszym przypadku jest takie samo jak połączenia HTTP / 1.1. , który przywraca limit połączenia SSE.
Myst
Zakładam, że połączenie websocket zużywa również zasoby serwera. samsaffron.com/archive/2015/12/29/websockets-caution-required . Zawsze dobrze jest mieć możliwość skonfigurowania dowolnej ilości kieszeni.
user1948585
jest prawdopodobne, że SSE zużyje podobne zasoby na większości serwerów (jeśli nie więcej zasobów ze względu na wciąż obecny stos HTTP i jego ograniczenia).
Myst
1
Ta odpowiedź jest poprawna. Limit 6 połączeń HTTP już nie istnieje podczas korzystania z HTTP / 2. Dowód: codepen.io/dunglas/pen/yLYxdxK?editors=1010 W przypadku HTTP / 2 serwer działa, a klient może negocjować maksymalną liczbę równoczesnych strumieni (domyślnie 100).
Kévin Dunglas