SSE vs WebSocket: którego rozwiązania czasu rzeczywistego użyć | We.Inc
Server-sent events czy WebSockety: EventSource i WebSocket obok siebie, ponowne łączenie, dane binarne, limity połączeń, pomocnik wyboru i minimalne serwery w Node dla obu.
Server-sent events strumieniują tekst z serwera do przeglądarki przez zwykłą odpowiedź HTTP, a API EventSource samo łączy się ponownie. WebSocket zamienia połączenie w dwukierunkowy kanał, który przenosi tekst lub dane binarne w obie strony. Używaj SSE do kanałów, powiadomień i postępu; używaj WebSocketów, gdy przeglądarka musi często wysyłać wiadomości z powrotem.
Obok siebie
Cecha
Server-sent events
WebSocket
Kierunek
Tylko z serwera do klienta
W obie strony jednocześnie
API przeglądarki
EventSource
WebSocket
Protokół
Zwykłe HTTP, text/event-stream
HTTP Upgrade, potem ws:// lub wss://
Dane
Tylko tekst UTF-8
Tekst lub dane binarne
Ponowne łączenie
Automatyczne, wznawia od Last-Event-ID
Musisz napisać je sam
Otwarte połączenia w HTTP/1
6 na przeglądarkę na domenę
Osobne limity, ustalane przez każdą przeglądarkę
Nie wiesz, którego potrzebuje Twoja funkcja? Zaznacz w pomocniku poniżej stwierdzenia, które są dla niej prawdziwe. Stosuje on te same reguły co tabela powyżej i mówi, które API pasuje i dlaczego.
Zaznacz każde stwierdzenie, które opisuje Twoją funkcję.
Przeczytaj rekomendację i podane uzasadnienie.
Skopiuj pasujący kod klienta i serwera z sekcji niżej.
Zmień URL i nazwy zdarzeń na własne i uruchom serwer w Node.
Co 15 do 30 sekund wysyłaj w strumieniu SSE linię komentarza, czyli dwukropek z tekstem, aby bezczynne proxy go nie zrywały.
Nadaj każdemu zdarzeniu SSE id. Gdy przeglądarka łączy się ponownie, odsyła tę wartość w nagłówku Last-Event-ID, a Twój serwer może odtworzyć to, co zostało pominięte.
Tam, gdzie możesz, serwuj SSE przez HTTP/2, bo limit sześciu połączeń w HTTP/1 jest współdzielony przez wszystkie otwarte karty z Twoją stroną.
Przy WebSocketach obserwuj bufferedAmount przed wysłaniem dużych porcji danych; samo API nie ma backpressure.
Najczęściej zadawane pytania
Czy przeglądarka może wysyłać dane do serwera przez SSE?
Nie przez sam strumień. Strumień zdarzeń płynie tylko z serwera do klienta, więc przeglądarka wysyła swoje wiadomości zwykłymi żądaniami fetch. Dla ruchu w obie strony, jak w czacie, WebSocket pasuje lepiej.
Jak powstrzymać EventSource przed ponownym łączeniem?
Wywołaj close() po stronie klienta. Po stronie serwera standard HTML mówi, że odpowiedź 204 No Content każe klientowi przestać się ponownie łączyć.
Czy mogę wysłać nagłówek Authorization przez EventSource?
Nie. Konstruktor przyjmuje tylko URL i obiekt opcji, którego jedynym ustawieniem jest withCredentials. Jeśli potrzebujesz własnych nagłówków, użyj ciasteczka, krótkotrwałego tokenu w URL lub czytnika opartego na fetch.
Czy SSE jest przestarzałe, skoro istnieją WebSockety?
Nie. Format text/event-stream to nadal dobry wybór dla jednokierunkowych kanałów, bo działa przez zwykłe serwery HTTP, proxy i uwierzytelnianie bez zmiany protokołu.
Które zużywa mniej zasobów serwera?
Oba utrzymują jedno długotrwałe połączenie na klienta, więc różnica jest niewielka. Ważniejsze jest to, czy Twój hosting w ogóle pozwala na długotrwałe odpowiedzi lub zmianę protokołu, więc najpierw sprawdź jego limity czasu trwania żądań.
Jak działają server-sent events
Serwer odpowiada na zwykły GET z Content-Type text/event-stream i utrzymuje odpowiedź otwartą. Każda wiadomość to kilka linii, takich jak event:, data: i id:, zakończonych pustą linią. Kilka linii data: w jednej wiadomości łączy się znakami nowej linii.
EventSource w przeglądarce parsuje ten strumień, wywołuje zdarzenie message dla wiadomości bez nazwy i zdarzenie nazwane dla pozostałych, a po zerwaniu samo łączy się ponownie. Linia retry: ustawia czas oczekiwania w milisekundach przed kolejną próbą.
Jak działają WebSockety
Klient zaczyna od żądania HTTP z nagłówkiem Upgrade, a serwer odpowiada 101 Switching Protocols. Od tej chwili połączenie przenosi ramki WebSocket, a nie HTTP, i każda strona może wysyłać dane w dowolnym momencie.
Ta swoboda ma swoją cenę. Piszesz własną logikę ponownego łączenia, własny format wiadomości, często JSON z polem type, i własny heartbeat. Proxy, które nie przekazuje nagłówka Upgrade, zatrzyma też połączenie, zanim się zacznie.
Szybka reguła
Jeśli przeglądarka głównie słucha, wybierz SSE. Wyniki na żywo, logi buildów, status zamówień, powiadomienia i strumieniowany tekst pasują tutaj.
Jeśli przeglądarka mówi tyle samo, ile słucha, albo dane są binarne, wybierz WebSocket. Gry wieloosobowe, edytory do współpracy i pokoje czatu pasują właśnie tam.
Server-sent events: minimalny kod
Serwer SSE w czystym Node
Nie potrzeba biblioteki. Odpowiedź pozostaje otwarta; każdy zapis to jedno zdarzenie, a linia komentarza chroni przed zamknięciem przez bezczynne proxy.
EventSource w przeglądarce
addEventListener używa nazwy zdarzenia ze strumienia. Ponowne łączenie odbywa się bez Twojego kodu.
WebSocket: minimalny kod
Serwer WebSocket z pakietem ws
Zainstaluj przez npm install ws. Ten serwer odsyła każdą wiadomość wielkimi literami do klienta, który ją wysłał.
WebSocket w przeglądarce z prostym ponownym łączeniem
W przeciwieństwie do EventSource nic nie łączy się ponownie za Ciebie, więc ten kod czeka chwilę po zamknięciu i otwiera nowe gniazdo.
Przeglądarka wysyła z powrotem wiele wiadomości, kilka na sekundę lub więcej
Dane są binarne, na przykład fragmenty audio lub bufory stanu gry
Klienci muszą nadrobić pominięte zdarzenia po zerwaniu połączenia
Ruch przechodzi przez proxy lub hosting obsługujące tylko zwykłe HTTP
Pasują server-sent events. Nic z tego, co zaznaczyłeś, nie wymaga dwukierunkowego kanału, a EventSource daje Ci ponowne łączenie i wznawianie za darmo.
Pasuje WebSocket. Potrzebujesz częstych wiadomości z przeglądarki lub danych binarnych, których strumień zdarzeń nie przeniesie.