Skip to content
Language:hu Author:Laborci Gergely
web-api

Változó adatok: polling, SSE, WebSocket és webhook

Célok

A lecke végére meg tudod különböztetni a négy frissítési mintát (polling, SSE, WebSocket, webhook) irány, kezdeményező és kapcsolattartósság szerint, és egy feladatra indokoltan tudsz választani közülük.

Miért nem elég egyszer lekérdezni?

A HTTP kérés–válasz alapú: a kliens kérdez, a szerver felel. Ez jó, ha az adat ritkán változik, de a férőhelyszám, az élő eredmények vagy egy közös szerkesztés állapota folyamatosan változhat. Ha a szerver nem tud magától szólni, a kliens felülete hamar elavul. A következő minták mind ezt a hiányt pótolják, de különböző irányban, különböző költséggel.

A hallgató a kurzusoldalon azt látja, hogy még három hely maradt. Közben mások is jelentkezhetnek. Egyik megoldás sem helyettesíti a szerver végső ellenőrzését: a „még van hely” kijelzés pillanatnyi információ, nem garantált foglalás.

flowchart TB
    P[Polling: ismételt klienskérés] --> C[Friss adat a kliensnek]
    S[SSE: szerveres eseményfolyam] --> C
    W[WebSocket: kétirányú kapcsolat] --> C
    H[Webhook: szerver értesít másik szervert] --> R[Másik rendszer]

Polling: időnként új kérés

Polling esetén a kliens meghatározott időközönként újra elkéri az adatot. A kipróbáló szerveren ez egyszerű HTTP-kérés:

$ curl http://localhost:8082/api/ferohely
{"kurzus":"webprog","szabad":3}

Egyszerű, mert a meglévő API-t használja. Hátránya: akkor is kérdez, ha nem történt változás, és a változás csak a következő lekéréskor látszik. Ritkán változó adathoz elfogadható; másodpercenkénti frissítésnél, sok kliensnél már költséges. A lekérdezési gyakoriság a felhasználói igény, a szerver terhelése és az adat változási sebessége együttes eredménye. Hiba esetén a kliens nem küldheti korlátlanul, azonnal újra ugyanazt (a szerver 429 válasszal védekezhet, 2.4).

Server-Sent Events: szerverről a kliens felé

A Server-Sent Events (SSE) HTTP-alapú eseményfolyam: a szerver a megnyitott kapcsolaton keresztül később is küldhet üzeneteket. Az MDN szerint a szervernek Content-Type: text/event-stream fejlécet kell küldenie, az üzenetek mező: érték sorokból állnak, és üres sor zár le egyet. A böngészőben az EventSource API fogadja, és a böngésző megszakadás esetén magától újracsatlakozik.

A kipróbáló szerver három eseményt küld fél másodperces közökkel (curl -N, hogy ne pufferelje a kimenetet):

$ curl -N http://localhost:8082/esemenyek
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache
Transfer-Encoding: chunked

id: 1
event: ferohely
data: {"kurzus":"webprog","szabad":2}

id: 2
event: ferohely
data: {"kurzus":"webprog","szabad":1}

id: 3
event: ferohely
data: {"kurzus":"webprog","szabad":0}

Minden eseménynek van azonosítója (id), neve (event) és adata (data). Az SSE egyirányú: szervertől a kliens felé. Ha a kliens műveletet kezdeményez, azt külön HTTP-kéréssel teszi. Az MDN szerint HTTP/1.1-en a böngészők kb. 6 SSE-kapcsolatot engednek böngészőnként és domainenként (HTTP/2-n ez a korlát nem áll fenn). Az SSE előnye az egyszerűbb, egyirányú modell, nem az, hogy mindig „valós idejűbb”.

WebSocket: kétirányú üzenetek

A WebSocket tartós, kétirányú üzenetváltást tesz lehetővé a kliens és a szerver között (az MDN szerint a kliensnek nem kell lekérdeznie a választ). Akkor lehet indokolt, ha mindkét fél gyakran kezdeményez: közös szerkesztésnél, interaktív játékban. A kapcsolat HTTP-kéréssel indul, amelyben a kliens protokollváltást (Upgrade) kér. Az RFC 6455 szerint a kérésben szerepel az Upgrade: websocket, a Connection: Upgrade, egy Sec-WebSocket-Key kulcs és a Sec-WebSocket-Version: 13. A szerver 101 Switching Protocols választ ad, és a Sec-WebSocket-Accept értékét a kulcsból számolja (a kulcshoz fix GUID-t fűz, SHA-1-gyel és base64-gyel).

A kipróbáló szerver az RFC példakulcsával:

$ curl -i --http1.1 http://localhost:8082/ws \
    -H 'Connection: Upgrade' -H 'Upgrade: websocket' \
    -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=='
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

A kapott Sec-WebSocket-Accept értéke megegyezik az RFC példájával, tehát a szerver helyesen számolta. (A példa csak a kézfogást mutatja; a tényleges kétirányú üzenetek keretezését nem implementáltuk.)

A kétirányúság több állapotkezelést jelent: a szervernek kezelnie kell a nyitott kapcsolatokat, a kliensnek a megszakadást, újracsatlakozást és a kihagyott változásokat. Egy ritkán frissülő kurzuslistához a WebSocket túlzás. A technológiát az igény határozza meg, nem a „valós idejű” szó hangzása. Az MDN azt is megjegyzi, hogy a WebSocket API-nak nincs visszanyomása (backpressure), ezért gyorsan érkező üzenetek kimeríthetik a memóriát vagy a processzort.

Webhook: rendszer értesít rendszert

A webhook esetén egy szolgáltatás esemény bekövetkezésekor HTTP-kérést küld egy másik szolgáltatás előre megadott címére. Például a jelentkezési rendszer értesíti a statisztikai rendszert egy új jelentkezésről. A fogadó félnek ellenőriznie kell, hogy az értesítés valóban a várt feladótól jön-e; erre gyakori módszer az aláírás: a küldő és a fogadó közös titkot tart, a küldő a törzsből ezzel HMAC (Hash-based Message Authentication Code) aláírást számol, és fejlécben elküldi.

A kipróbáló fogadó ellenőrzi az aláírást (SHA-256 HMAC, X-Alairas fejléc):

$ curl -i -X POST http://localhost:8082/webhook -H "X-Alairas: 6b1b1ead...8ec3" \
    -d '{"esemeny":"uj_jelentkezes","kurzus":"webprog"}'
HTTP/1.1 200 OK
elfogadva

$ curl -i -X POST http://localhost:8082/webhook -H "X-Alairas: 0000" \
    -d '{"esemeny":"uj_jelentkezes","kurzus":"webprog"}'
HTTP/1.1 401 Unauthorized
ervenytelen alairas

Az aláírás a törzsből és a közös titokból származik; a hamisító nem tudja előállítani. A fogadónak kezelnie kell az ismételt vagy sikertelen kézbesítést is (a küldő újrapróbálhat), ezért a fogadó műveletnek idempotensnek kell lennie (2.3).

Hogyan válasszunk?

Minta Irány Kapcsolat Mikor jó?
Polling kliens → szerver kérdez kérésenként új ritkán változó adat, egyszerűség
SSE szerver → kliens tartós, egyirányú élő státusz, hírfolyam
WebSocket kétirányú tartós közös szerkesztés, játék, gyakori kétirányú üzenet
Webhook szerver → szerver eseményenként egy kérés rendszerek közötti értesítés

Végigvezetett példa: a Kurzuspont férőhelyszáma

Igény Választás Indok
Az oldal 30 másodpercenként frissítse a szabad helyek számát polling egyszerű, a meglévő API elég
Jelentkezés nyitásakor a szám azonnal csökkenjen mindenki képernyőjén SSE a szerver küldi a változást, a kliens nem küld
A jelentkezések értesítsék az egyetemi statisztikai rendszert webhook szerver–szerver esemény
Közös tanulócsoport-szerkesztő jegyzetekhez WebSocket kétirányú, gyakori üzenetek

A „szabad: 0” kijelzés semmiképp nem foglalás: a jelentkezés pillanatában a szervernek külön ellenőriznie kell a helyet (2.4: 409).

Gyakori tévhitek

Állítás Pontosítás
„Valós idejű frissítéshez mindig WebSocket kell.” Polling vagy SSE is megfelelhet az igénynek.
„SSE-ben mindkét fél ugyanazon a csatornán küld eseményt.” Az SSE szervertől kliens felé tartó folyam.
„A webhook a böngésző értesítése.” Jellemzően szolgáltatás küld HTTP-kérést másik szolgáltatásnak.
„A kijelzett szabad hely biztos foglalás.” A szervernek a jelentkezéskor külön kell ellenőriznie.
„A webhook aláírás nélkül is megbízható.” Bárki küldhet kérést a címre; az aláírás igazolja a feladót.

Röviden

  • A polling ismételt kérdezés, az SSE egyirányú szerver→kliens folyam, a WebSocket tartós kétirányú csatorna, a webhook szolgáltatások közötti esemény-kérés.
  • A WebSocket HTTP-kéréssel indul, és 101 Switching Protocols válasszal vált protokollt.
  • A webhook-fogadónak ellenőriznie kell a feladót (aláírás), és kezelnie kell az ismétlést.
  • A választás irányon, gyakoriságon és költségen múlik.
  • A kijelzett állapot nem foglalás.

Ellenőrző kérdések

  1. Miben különbözik a polling az SSE-től?
  2. Mi a 101 Switching Protocols szerepe a WebSocket kézfogásában?
  3. Miért kell a webhook-fogadónak ellenőriznie az aláírást?
  4. Melyik mintát választanád egy ritkán frissülő hírlistához, és melyiket közös szerkesztéshez?

Tanulási források

Prerequisites (2)

  • webes API
  • HTTP

Teaches (4)

  • polling
  • Server-Sent Events
  • WebSocket
  • webhook