Utilizarea SSE în loc de WebSockets pentru fluxul de date unidirecțional prin HTTP/2
Publicat: 2022-03-10Când construiți o aplicație web, trebuie să luați în considerare ce fel de mecanism de livrare vor folosi. Să presupunem că avem o aplicație multiplatformă care funcționează cu date în timp real; o aplicație de bursă care oferă posibilitatea de a cumpăra sau vinde acțiuni în timp real. Această aplicație este compusă din widget-uri care aduc o valoare diferită diferiților utilizatori.
Când vine vorba de livrarea datelor de la server către client, ne limităm la două abordări generale: client pull sau server push . Ca exemplu simplu cu orice aplicație web, clientul este browserul web. Când site-ul web din browser-ul dvs. solicită serverului date, acest lucru se numește client pull . Invers, atunci când serverul trimite în mod proactiv actualizări către site-ul dvs., se numește server push .
În prezent, există câteva modalități de a le implementa:
- Sondaj lung/scurt (client pull)
- WebSockets (pus de server)
- Evenimente trimise de server (server push).
Vom arunca o privire în profunzime asupra celor trei alternative după ce vom stabili cerințele pentru cazul nostru de afaceri.
Cazul de afaceri
Pentru a putea livra rapid widget-uri noi pentru aplicația noastră de bursă și le putem conecta fără redistribuire a întregii platforme, avem nevoie ca acestea să fie autonome și să-și gestioneze propriile date I/O. Widgeturile nu sunt cuplate între ele în niciun fel. În cazul ideal, toți se vor abona la un punct final API și vor începe să primească date de la acesta. Pe lângă un timp mai rapid de introducere pe piață a noilor funcții, această abordare ne oferă posibilitatea de a exporta conținut pe site-uri web ale unor terțe părți, în timp ce widget-urile noastre aduc singure tot ce au nevoie.
Principalul capcan aici este că numărul de conexiuni va crește liniar cu numărul de widget-uri pe care le avem și vom atinge limita browserelor pentru numărul de solicitări HTTP gestionate simultan.
Datele pe care le vor primi widget-urile noastre sunt compuse în principal din numere și actualizări ale numerelor lor: răspunsul inițial conține zece acțiuni cu unele valori de piață pentru ele. Aceasta include actualizări de adăugare/eliminare de stocuri și actualizări ale valorilor de piață ale celor prezentate în prezent. Transferăm cantități mici de șiruri JSON pentru fiecare actualizare cât mai repede posibil.
HTTP/2 oferă multiplexarea cererilor care provin din același domeniu, ceea ce înseamnă că putem obține o singură conexiune pentru răspunsuri multiple. Se pare că ar putea rezolva problema noastră. Începem prin a explora diferitele opțiuni pentru a obține datele și a vedea ce putem obține din ele.
- Vom folosi NGINX pentru echilibrarea încărcării și proxy pentru a ne ascunde toate punctele finale în spatele aceluiași domeniu. Acest lucru ne va permite să folosim multiplexarea HTTP/2 imediată.
- Dorim să folosim eficient rețeaua și bateria dispozitivelor mobile.
Alternativele
Sondaj lung

Client pull este echivalentul implementării software a copilului enervant care stă pe bancheta din spate a mașinii tale și întreabă în mod constant: „Am ajuns încă?” Pe scurt, clientul cere serverului date. Serverul nu are date și așteaptă o perioadă de timp înainte de a trimite răspunsul:
- Dacă apare ceva în timpul așteptării, serverul îl trimite și închide cererea;
- Dacă nu este nimic de trimis și este atins timpul maxim de așteptare, serverul trimite un răspuns că nu există date;
- În ambele cazuri, clientul deschide următoarea solicitare de date;
- Spumă, clătește, repetă.
Apelurile AJAX funcționează pe protocolul HTTP, ceea ce înseamnă că cererile către același domeniu ar trebui să fie multiplexate în mod implicit. Cu toate acestea, ne-am confruntat cu mai multe probleme în încercarea de a face ca acestea să funcționeze după cum este necesar. Unele dintre capcanele pe care le-am identificat cu abordarea widget-urilor:
Antete deasupra capului
Fiecare cerere și răspuns la sondaj este un mesaj HTTP complet și conține un set complet de anteturi HTTP în cadrul mesajului. În cazul nostru în care avem mesaje frecvente mici, anteturile reprezintă de fapt cel mai mare procent din datele transmise. Sarcina utilă reală este mult mai mică decât totalul de octeți transmiși (de exemplu, 15 KB de anteturi pentru 5 KB de date).Latența maximă
După ce serverul răspunde, nu mai poate trimite date către client până când clientul trimite următoarea solicitare. În timp ce latența medie pentru sondarea lungă este aproape de un tranzit de rețea, latența maximă este peste trei tranzite de rețea: răspuns, cerere, răspuns. Cu toate acestea, din cauza pierderii și retransmisiei pachetelor, latența maximă pentru orice protocol TCP/IP va fi mai mare de trei tranzite de rețea (evitabilă cu pipelining HTTP). În timp ce în conexiunea LAN directă, aceasta nu este o problemă mare, devine una în timp ce cineva este în mișcare și comută celulele de rețea. Într-o anumită măsură, acest lucru se observă cu SSE și WebSockets, dar efectul este cel mai mare cu sondajele.Stabilirea conexiunii
Deși poate fi evitat prin utilizarea unei conexiuni HTTP persistente reutilizabile pentru multe solicitări de sondare, este dificil să programați în mod corespunzător toate componentele dvs. pentru a interoga pe durate scurte pentru a menține conexiunea vie. În cele din urmă, în funcție de răspunsurile serverului, sondajele dvs. vor fi desincronizate.Degradarea performanței
Un client (sau server) de interogare lung care este sub încărcare are o tendință naturală de a degrada performanța cu prețul latenței mesajului. Când se întâmplă acest lucru, evenimentele care sunt transmise clientului vor fi în coadă. Acest lucru depinde cu adevărat de implementare; în cazul nostru, trebuie să cumulăm toate datele pe măsură ce trimitem evenimente de adăugare/eliminare/actualizare către widget-urile noastre.Timeouts
Solicitările lungi de sondaj trebuie să rămână în așteptare până când serverul are ceva de trimis clientului. Acest lucru poate duce la închiderea conexiunii de către serverul proxy dacă rămâne inactiv prea mult timp.Multiplexarea
Acest lucru se poate întâmpla dacă răspunsurile au loc în același timp printr-o conexiune HTTP/2 persistentă. Acest lucru poate fi dificil de făcut, deoarece răspunsurile la sondaje nu pot fi cu adevărat sincronizate.
Mai multe despre problemele din lumea reală pe care le-ar putea experimenta cu sondaje lungi pot fi găsite aici .
WebSockets

Ca un prim exemplu al metodei server push , ne vom uita la WebSockets.
Prin MDN:
WebSockets este o tehnologie avansată care face posibilă deschiderea unei sesiuni de comunicare interactivă între browserul utilizatorului și un server. Cu acest API, puteți trimite mesaje către un server și puteți primi răspunsuri bazate pe evenimente fără a fi nevoie să interogați serverul pentru un răspuns.
Acesta este un protocol de comunicații care oferă canale de comunicație full-duplex printr-o singură conexiune TCP.
Atât HTTP, cât și WebSockets sunt localizate la nivelul aplicației din modelul OSI și, ca atare, depind de TCP la nivelul 4.
- Aplicație
- Prezentare
- Sesiune
- Transport
- Reţea
- Legătură de date
- Fizic
RFC 6455 afirmă că WebSocket „este proiectat să funcționeze peste porturile HTTP 80 și 443, precum și să accepte proxy-uri și intermediari HTTP”, făcându-l astfel compatibil cu protocolul HTTP. Pentru a obține compatibilitate, strângerea de mână WebSocket utilizează antetul de actualizare HTTP pentru a trece de la protocolul HTTP la protocolul WebSocket.
Există și un articol foarte bun care explică tot ce trebuie să știi despre WebSockets pe Wikipedia. Vă încurajez să o citiți.
După ce am stabilit că prizele ar putea funcționa cu adevărat pentru noi, am început să le explorăm capacitățile în cazul nostru de afaceri și am lovit perete după perete.
Servere proxy : în general, există câteva probleme diferite cu WebSockets și proxy:
- Prima este legată de furnizorii de servicii de internet și de modul în care aceștia își gestionează rețelele. Probleme cu raza proxy-urilor blocate porturile și așa mai departe.
- Al doilea tip de probleme este legat de modul în care proxy-ul este configurat pentru a gestiona traficul HTTP nesecurizat și conexiunile de lungă durată (impactul este diminuat cu HTTPS).
- A treia problemă „cu WebSockets, ești forțat să rulezi proxy-uri TCP, spre deosebire de proxy-urile HTTP. Proxy-urile TCP nu pot injecta anteturi, rescrie URL-uri sau pot îndeplini multe dintre rolurile de care în mod tradițional lăsăm proxy-urile noastre HTTP să se ocupe.”
Un număr de conexiuni : celebra limită de conexiune pentru solicitările HTTP care se învârte în jurul numărului 6, nu se aplică pentru WebSockets. 50 de prize = 50 de conexiuni. Zece file de browser cu 50 de prize = 500 de conexiuni și așa mai departe. Deoarece WebSocket este un protocol diferit pentru livrarea datelor, nu este multiplexat automat prin conexiuni HTTP/2 (nu rulează deloc peste HTTP). Implementarea multiplexării personalizate atât pe server, cât și pe client este prea complicată pentru a face socket-urile utile în cazul de afaceri specificat. În plus, aceasta cuplează widget-urile noastre cu platforma noastră, deoarece vor avea nevoie de un fel de API pe client la care să se aboneze și nu le putem distribui fără el.
Echilibrarea sarcinii (fără multiplexare) : Dacă fiecare utilizator deschide
n
număr de socluri, echilibrarea corectă a sarcinii este foarte complicată. Când serverele dvs. sunt supraîncărcate și trebuie să creați instanțe noi și să le terminați pe cele vechi, în funcție de implementarea software-ului dvs., acțiunile care sunt întreprinse la „reconectare” pot declanșa un lanț masiv de reîmprospătări și noi solicitări de date care vă vor supraîncărca sistemul. . WebSocket-urile trebuie menținute atât pe server, cât și pe client. Nu este posibil să mutați conexiunile socket pe un alt server dacă cel actual are o sarcină mare. Acestea trebuie să fie închise și redeschise.DoS : Acest lucru este de obicei gestionat de proxy-urile HTTP front-end care nu pot fi gestionate de proxy-urile TCP care sunt necesare pentru WebSockets. Se poate conecta la socket și începe să vă inunde serverele cu date. WebSockets vă lasă vulnerabil la acest tip de atacuri.
Reinventarea roții : Cu WebSockets, trebuie să se ocupe de o mulțime de probleme de care se rezolvă pe cont propriu în HTTP.
Mai multe despre problemele din lumea reală cu WebSockets pot fi citite aici.
Unele cazuri bune de utilizare pentru WebSockets sunt chat-urile și jocurile cu mai mulți jucători în care beneficiile depășesc problemele de implementare. Principalul lor avantaj fiind comunicarea duplex, iar noi nu avem nevoie de ea, trebuie să mergem mai departe.
Impact
Obținem cheltuieli operaționale sporite în ceea ce privește dezvoltarea, testarea și scalarea; software-ul și infrastructura sa IT cu ambele: sondaje și WebSockets.
Avem aceeași problemă pe dispozitivele mobile și rețelele cu ambele. Designul hardware al acestor dispozitive menține o conexiune deschisă, menținând în viață antena și conexiunea la rețeaua celulară. Acest lucru duce la reducerea duratei de viață a bateriei, la căldură și, în unele cazuri, la taxe suplimentare pentru date.
Dar de ce avem încă probleme cu dispozitivele mobile?
Să luăm în considerare modul în care dispozitivul mobil implicit se conectează la Internet:
O explicație simplă a modului în care funcționează rețeaua mobilă: de obicei, dispozitivele mobile au o antenă de putere redusă care poate primi date de la o celulă. În acest fel, odată ce dispozitivul primește date de la un apel primit, pornește antena full-duplex pentru a stabili apelul. Aceeași antenă este folosită ori de câte ori doriți să efectuați un apel sau să accesați Internetul (dacă nu este disponibil WiFi). Antena full-duplex trebuie să stabilească o conexiune la rețeaua celulară și să facă ceva autentificare. Odată ce conexiunea este stabilită, există o anumită comunicare între dispozitivul dvs. și celulă pentru a face cererea noastră de rețea. Suntem redirecționați către proxy-ul intern al furnizorului de servicii mobile care se ocupă de solicitările de pe internet. De atunci, procedura este deja cunoscută: întreabă un DNS unde se află de fapt www.domainname.ext
, primind URI-ul resursei și în cele din urmă fiind redirecționat către aceasta.
Acest proces, după cum vă puteți imagina, consumă destul de multă energie a bateriei. Acesta este motivul pentru care furnizorii de telefoane mobile oferă un timp de așteptare de câteva zile și un timp de convorbire în doar câteva ore.
Fără WiFi, atât WebSockets, cât și sondajele necesită ca antena full-duplex să funcționeze aproape constant. Astfel, ne confruntăm cu un consum crescut de date și un consum crescut de energie - și, în funcție de dispozitiv -, de asemenea, căldură.

Până când lucrurile par sumbre, se pare că va trebui să reconsiderăm cerințele de afaceri pentru aplicația noastră. Ne scapa ceva?
SSE

Prin MDN:
„Interfața EventSource este folosită pentru a primi evenimente trimise de server. Se conectează la un server prin HTTP și primește evenimente în format text/flux de evenimente fără a închide conexiunea.”
Principala diferență față de sondaj este că obținem o singură conexiune și păstrăm un flux de evenimente care trece prin acesta. Sondajul îndelungat creează o nouă conexiune pentru fiecare tragere - de exemplu, anteturile de deasupra capului și alte probleme cu care ne-am confruntat acolo.
Prin html5doctor.com:
Evenimentele trimise de server sunt evenimente în timp real emise de server și primite de browser. Ele sunt similare cu WebSockets prin faptul că se întâmplă în timp real, dar sunt foarte mult o metodă de comunicare unidirecțională de la server.
Pare destul de ciudat, dar după luare în considerare - fluxul nostru principal de date este de la server la client și în mult mai puține ocazii de la client la server.
Se pare că putem folosi acest lucru pentru cazul principal de afaceri al furnizării de date. Putem rezolva achizițiile clienților prin trimiterea unei noi solicitări, deoarece protocolul este unidirecțional și clientul nu poate trimite mesaje către server prin intermediul acestuia. În cele din urmă, aceasta va avea o întârziere a antenei full-duplex pentru a porni pe dispozitivele mobile. Cu toate acestea, putem trăi cu asta din când în când - această întârziere este măsurată în milisecunde până la urmă.
Caracteristici unice
- Fluxul de conexiune vine de la server și este doar pentru citire.
- Ei folosesc cereri HTTP obișnuite pentru conexiunea persistentă, nu un protocol special. Primirea multiplexării prin HTTP/2 din cutie.
- Dacă conexiunea se întrerupe, EventSource declanșează un eveniment de eroare și încearcă automat să se reconecteze. Serverul poate controla, de asemenea, timeout-ul înainte ca clientul să încerce să se reconnecteze (explicat în mai multe detalii mai târziu).
- Clienții pot trimite un ID unic cu mesaje. Când un client încearcă să se reconecteze după o conexiune întreruptă, va trimite ultimul ID cunoscut. Apoi, serverul poate vedea că clientul a
n
un număr de mesaje și poate trimite mesajele neîntârziate la reconectare.
Exemplu de implementare client
Aceste evenimente sunt similare cu evenimentele JavaScript obișnuite care apar în browser - cum ar fi evenimentele de clic - cu excepția faptului că putem controla numele evenimentului și datele asociate acestuia.
Să vedem previzualizarea simplă a codului pentru partea client:
// subscribe for messages var source = new EventSource('URL'); // handle messages source.onmessage = function(event) { // Do something with the data: event.data; };
Ceea ce vedem din exemplu este că partea clientului este destul de simplă. Se conectează la sursa noastră și așteaptă să primească mesaje.
Pentru a permite serverelor să transmită date către pagini web prin HTTP sau folosind protocoale server-push dedicate, specificația introduce interfața „EventSource” pe client. Utilizarea acestui API constă în crearea unui obiect `EventSource` și înregistrarea unui ascultător de evenimente.
Implementarea clientului pentru WebSockets arată foarte asemănătoare cu aceasta. Complexitatea socket-urilor constă în infrastructura IT și implementarea serverului.
EventSource
Fiecare obiect EventSource
are următorii membri:
- URL: setat în timpul construcției.
- Solicitare: inițial este nulă.
- Timp de reconectare: valoare în ms (valoare definită de user-agent).
- ID ultimul eveniment: inițial un șir gol.
- Stare gata: starea conexiunii.
- CONECTARE (0)
- DESCHIS (1)
- ÎNCHIS (2)
În afară de URL, toate sunt tratate ca private și nu pot fi accesate din exterior.
Evenimente integrate:
- Deschis
- Mesaj
- Eroare
Gestionarea caderilor de conexiune
Conexiunea este restabilită automat de către browser dacă se renunță. Serverul poate trimite timeout pentru a reîncerca sau închide definitiv conexiunea. Într-un astfel de caz, browserul se va conforma fie să încerce să se reconnecteze după expirarea timpului, fie să nu încerce deloc dacă conexiunea a primit un mesaj de terminare. Pare destul de simplu - și chiar este.
Exemplu de implementare a serverului
Ei bine, dacă clientul este atât de simplu, poate implementarea serverului este complexă?
Ei bine, handlerul de server pentru SSE poate arăta astfel:
function handler(response) { // setup headers for the response in order to get the persistent HTTP connection response.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); // compose the message response.write('id: UniqueID\n'); response.write("data: " + data + '\n\n'); // whenever you send two new line characters the message is sent automatically }
Definim o funcție care va gestiona răspunsul:
- Configurați antetele
- Creați mesaj
- Trimite
Rețineți că nu vedeți un apel la metoda send()
sau push()
. Acest lucru se datorează faptului că standardul definește că mesajul va fi trimis imediat ce primește două caractere \n\n
ca în exemplul: response.write("data: " + data + '\n\n');
. Acest lucru va împinge imediat mesajul către client. Vă rugăm să rețineți că data
trebuie să fie un șir cu evadare și nu au caractere de linie noi la sfârșitul acestuia.
Constructia mesajului
După cum am menționat mai devreme, mesajul poate conține câteva proprietăți:
- ID
Dacă valoarea câmpului nu conține U+0000 NULL, atunci setați ultimul buffer ID eveniment la valoarea câmpului. În caz contrar, ignorați câmpul. - Date
Adăugați valoarea câmpului la tamponul de date, apoi adăugați un singur caracter U+000A LINE FEED (LF) la tamponul de date. - Eveniment
Setați tamponul tip eveniment la valoarea câmpului. Acest lucru duce laevent.type
obținerea numelui dvs. de eveniment personalizat. - Reîncercați
Dacă valoarea câmpului constă numai din cifre ASCII, atunci interpretați valoarea câmpului ca un număr întreg în baza zece și setați timpul de reconectare a fluxului de evenimente la acel număr întreg. În caz contrar, ignorați câmpul.
Orice altceva va fi ignorat. Nu putem introduce propriile noastre domenii.
Exemplu cu event
adăugat:
response.write('id: UniqueID\n'); response.write('event: add\n'); response.write('retry: 10000\n'); response.write("data: " + data + '\n\n');
Apoi, pe client, acest lucru este gestionat cu addEventListener
ca atare:
source.addEventListener("add", function(event) { // do stuff with data event.data; });
Puteți trimite mai multe mesaje separate printr-o nouă linie, atâta timp cât furnizați ID-uri diferite.
... id: 54 event: add data: "[{SOME JSON DATA}]" id: 55 event: remove data: JSON.stringify(some_data) id: 56 event: remove data: { data: "msg" : "JSON data"\n data: "field": "value"\n data: "field2": "value2"\n data: }\n\n ...
Acest lucru simplifică foarte mult ceea ce putem face cu datele noastre.
Cerințe specifice serverului
În timpul POC pentru back-end, am identificat că are anumite particularități care trebuie abordate pentru a avea o implementare funcțională a SSE. În cel mai bun caz, veți folosi un server bazat pe bucla de evenimente precum NodeJS, Kestrel sau Twisted. Ideea este că cu soluția bazată pe fire veți avea un fir per conexiune → 1000 conexiuni = 1000 fire. Cu soluția de buclă de evenimente, veți avea un fir pentru 1000 de conexiuni.
- Puteți accepta cereri EventSource numai dacă cererea HTTP spune că poate accepta tipul MIME de flux de evenimente;
- Trebuie să păstrați o listă cu toți utilizatorii conectați pentru a emite noi evenimente;
- Ar trebui să ascultați conexiunile întrerupte și să le eliminați din lista de utilizatori conectați;
- Opțional, ar trebui să păstrați un istoric al mesajelor, astfel încât clienții care se reconectează să poată prinde din urmă mesajele pierdute.
Funcționează conform așteptărilor și pare magic la început. Obținem tot ce ne dorim pentru ca aplicația noastră să funcționeze într-un mod eficient. Ca și în cazul tuturor lucrurilor care arată prea bine pentru a fi adevărate, uneori ne confruntăm cu unele probleme care trebuie abordate. Cu toate acestea, ele nu sunt complicate de implementat sau de folosit:
Se știe că serverele proxy vechi, în anumite cazuri, renunță la conexiunile HTTP după o perioadă scurtă de timp. Pentru a se proteja împotriva unor astfel de servere proxy, autorii pot include o linie de comentariu (una care începe cu caracterul „:”) la fiecare 15 secunde sau cam asa ceva.
Autorii care doresc să relaționeze conexiunile surselor de evenimente între ele sau cu anumite documente furnizate anterior ar putea descoperi că bazarea pe adrese IP nu funcționează, deoarece clienții individuali pot avea mai multe adrese IP (datorită faptului că au mai multe servere proxy) și adresele IP individuale pot avea clienți multipli (datorită partajării unui server proxy). Este mai bine să includeți un identificator unic în document atunci când este servit și apoi să treceți acel identificator ca parte a adresei URL atunci când este stabilită conexiunea.
Autorii sunt atenționați, de asemenea, că fragmentarea HTTP poate avea efecte negative neașteptate asupra fiabilității acestui protocol, în special dacă fragmentarea este realizată de un alt strat care nu cunoaște cerințele de sincronizare. Dacă aceasta este o problemă, fragmentarea poate fi dezactivată pentru difuzarea fluxurilor de evenimente.
Clienții care acceptă limitarea conexiunii pe server HTTP ar putea avea probleme atunci când deschid mai multe pagini de pe un site dacă fiecare pagină are o sursă de evenimente pe același domeniu. Autorii pot evita acest lucru folosind mecanismul relativ complex de utilizare a numelor de domenii unice pe conexiune sau permițând utilizatorului să activeze sau să dezactiveze funcționalitatea EventSource pe pagină sau prin partajarea unui singur obiect EventSource folosind un lucrător partajat.
Suport pentru browser și Polyfills: Edge rămâne în urmă cu această implementare, dar este disponibil un polyfill care vă poate salva. Cu toate acestea, cel mai important caz pentru SSE este făcut pentru dispozitivele mobile în care IE/Edge nu are o cotă de piață viabilă.
Unele dintre poliumpluturile disponibile:
- Yaffle
- amvtek
- remy
Push fără conexiune și alte caracteristici
Agenții utilizatori care rulează în medii controlate, de exemplu, browsere pe telefoane mobile legate de operatori anumi, pot descărca gestionarea conexiunii la un proxy din rețea. Într-o astfel de situație, agentul utilizator în scopuri de conformitate este considerat că include atât software-ul receptorului, cât și proxy-ul de rețea.
De exemplu, un browser de pe un dispozitiv mobil, după ce a stabilit o conexiune, ar putea detecta că se află într-o rețea de suport și poate solicita ca un server proxy din rețea să preia gestionarea conexiunii. Termenul pentru o astfel de situație ar putea fi următorul:
- Browserul se conectează la un server HTTP la distanță și solicită resursa specificată de autor în constructorul EventSource.
- Serverul trimite mesaje ocazionale.
- Între două mesaje, browserul detectează că este inactiv, cu excepția activității de rețea implicată în menținerea conexiunii TCP vie și decide să treacă în modul de repaus pentru a economisi energie.
- Browserul se deconectează de la server.
- Browserul contactează un serviciu din rețea și solicită ca serviciul, un „proxy push”, să mențină conexiunea.
- Serviciul „push proxy” contactează serverul HTTP la distanță și solicită resursa specificată de autor în constructorul EventSource (incluzând eventual un antet HTTP
Last-Event-ID
etc.). - Browserul permite dispozitivului mobil să intre în somn.
- Serverul trimite un alt mesaj.
- Serviciul „push proxy” folosește o tehnologie precum OMA push pentru a transmite evenimentul către dispozitivul mobil, care se trezește doar suficient pentru a procesa evenimentul și apoi revine în stare de repaus.
Acest lucru poate reduce utilizarea totală a datelor și, prin urmare, poate duce la economii considerabile de energie.
Pe lângă implementarea API-ului existent și a formatului text/flux de evenimente, așa cum este definit de specificație și în moduri mai distribuite (așa cum este descris mai sus), pot fi acceptate formatele de încadrare a evenimentelor definite de alte specificații aplicabile.
rezumat
După POC lungi și exhaustive, inclusiv implementări de server și client, se pare că SSE este răspunsul la problemele noastre cu livrarea datelor. Există și câteva capcane cu el, dar s-au dovedit a fi trivial de remediat.
Iată cum arată configurația noastră de producție în cele din urmă:

Obținem următoarele de la NGINX:
- Proxy la punctele finale API în diferite locuri;
- HTTP/2 și toate beneficiile sale, cum ar fi multiplexarea pentru conexiuni;
- Echilibrarea sarcinii;
- SSL.
În acest fel, ne gestionăm livrarea datelor și certificatele într-un singur loc, în loc să o facem pe fiecare punct final separat.
Principalele beneficii pe care le obținem din această abordare sunt:
- Date eficiente;
- Implementare mai simplă;
- Este multiplexat automat prin HTTP/2;
- Limitează numărul de conexiuni pentru datele de pe client la una;
- Oferă un mecanism de economisire a bateriei prin descărcarea conexiunii la un proxy.
SSE nu este doar o alternativă viabilă la celelalte metode de furnizare de actualizări rapide; se pare că se află într-o ligă proprie când vine vorba de optimizări pentru dispozitive mobile. Nu există costuri generale în implementarea sa în comparație cu alternativele. În ceea ce privește implementarea pe partea serverului, nu este mult diferită de sondaj. Pe client, este mult mai simplu decât sondarea, deoarece necesită un abonament inițial și atribuirea de handlere de evenimente - mult similar cu modul în care sunt gestionate WebSockets.
Verificați demonstrația codului dacă doriți să obțineți o implementare simplă client-server.
Resurse
- „Probleme cunoscute și cele mai bune practici pentru utilizarea sondajului lung și a transmiterii în flux în HTTP bidirecțional”, IETF (PDF)
- Recomandare W3C, W3C
- „Va supraviețui WebSocket HTTP/2?”, Allan Denis, InfoQ
- „Actualizări în flux cu evenimente trimise de server”, Eric Bidelman, HTML5 Rocks
- „Aplicații Data Push cu HTML5 SSE”, Darren Cook, O'Reilly Media