WebSockets и SSE
1) Կարճ ՝ ի՞ նչ և ինչի համար։
No Socket (WS/WFC) - HTTP միացությունների ապգրեյդը մինչև ամբողջական դուպլեքսային ջրանցքը։ Հարմար է չատների, խաղերի, համագործակցությունների, երկբևեռ հեռուստատեսության համար։
Server-Sent Events (SSE) - միակողմանի հոսք սերվերից դեպի զննարկիչ (MIME '07/event-stream ")։ Իդեալական է հյուսողների, ծանուցումների, գնանշումների, առաջադրանքների առաջընթացի համար։ Հաճախորդը '«EventSource»։
Ընտրության կանոնը
Անհրաժեշտ է հաճախորդից իրական ժամանակում (հաճախ և շատ) միացնել WindowSocket-ը։
Միայն սերվերից նորարարությունները, համատեղելիությունը և պարզությունը ավելի կարևոր են, քան SSE-ն։
2) Ցանցը և արձանագրությունները
2. 1 Տրանսպորտ և համատեղելիություն
No Socket: սկսվում է որպես HTTP 'GET... Upgrade: websocket` (HTTP/1. 1). HTTP/2-ի համար հնարավոր է RFC 8441 (CONTS + ': websocket = websocket "), աջակցությունը կախված է հաճախորդներից։ Աշխատում է TFC-ի վերևում (WFC), անպայման վաճառքում։
SSE 'սովորական երկար HTTP պատասխանը («200 OK») հոսքով։ Հիանալի է HTTP/1 միջոցով։ 1/2/3, համատեղենք CDN/112-ի հետ (եթե երկար կոններ չեն փակում)։
2. 2 Windows/հավասարակշռիչներ/CDN
Շվեյցարիան 'երկար գոյատևող միգրանտների, քայլերի և թայմաուտների, sticky-նստաշրջանների աջակցություն (եթե պետության վիճակը)։
WS-ի համար միացրեք «proxy _ read _ timeout», «upgrade» -- գուշակները, limita-ը։
SSE-ի համար, համոզվեք, որ ֆորումը չի բավարարում պատասխանը (հակառակ դեպքում հաճախորդը չի տեսնի իրադարձությունները ժամանակին)։
3) Հաղորդագրությունների մոդելը և հոսքի կառավարումը
Express Socket: կադրեր տեքստը կամ երկուական; կա 'ping/pong ", բայց ներկառուցված backpressure-ը չկա' իրականացրեք (հերթեր, պատուհաններ, drop-policy)։
SSE 'տեքստային իրադարձություններ (UTF-8); հաճախորդը ներկառուցված գիտի reconn.ru ուշացումով; սերվերը կարող է տալ «retry: »։ Կա «id:» և «Lox-Event-ID» վերնագիրը 'ճիշտ դիրքից խուսափելու համար։
Backpressure (ընդհանուր պրակտիկա)
Քվոտտացրեք per հաճախորդի հաղորդագրությունները։
Սահմանափակեք չլսված իրադարձությունների հերթը։ հալեցնելիս 'ցածր պրիմիտիվ/համախմբել։
WS-ի համար օգտագործեք «սայթաքող պատուհան» և ACK-սխեմա հավելվածի մակարդակում։
4) Վասիլեվիչը
4. 1 Դետեկտիվ և keepalive
WS 'ուղարկեք «ping» յուրաքանչյուր N վայրկյանում; Timaut- ի բացը reconn.ru է, էքսպոնենցիալ backoff + jitter։
SSE 'Server սաղավարտը «մեկնաբանություններ» է: <& n' որպես heartbeat, որպեսզի միացումը չհաշվի idle; հաճախորդը ինքնին փոխպատվաստվելու է։
4. 2 Վերականգնումը
WS 'պահեք wwww.set/sequence հաղորդագրությունները և խնդրեք դելտա reconnations-ից հետո։
SSE 'օգտագործեք «id: » Յուրաքանչյուր իրադարձության համար և «Lox-Event-ID», պահանջելով, սերվերը բաց են թողնում։
5) Վավերացումը և հեղինակային իրավունքը
JWT Bearer-ը URL-ում (WS) անվտանգ չէ (լոգարաններում արտահոսք)։ Օգտագործեք վերնագիր (առաջնային HTTP-handshaik-ի միջոցով) կամ «Secure», «Windows Only», «SoftSite» դրոշներով։
Հնարավոր է mTSA (հատկապես B2B), ինչպես նաև ստորագրությունները (HMAC) սկզբնական հարցման վերևում։
SSE-ի համար կուկներով հիշեք SNS-ի մասին («Systel-Masl-Allow-Origin», «Allow-Credentials»)։
Հոսանքի տարհանումը 'մի կոտրեք հոսանքը։ Փոխանցեք «շուտով կավարտվի» ռուսական հաճախորդը կփոխանցի կապը նոր հոսանքի հետ։
6) Տվյալների և ագրեսիայի ձևաչափը
Windows Socket: Ներառեք permessage-sylate զգույշ (CPU); խուսափեք արդեն սեղմված ձևերի թեմերից (Coro, Avro)։ Binar payload ավելի խնայողական է, քան JSON-ը։
SSE 'սա տեքստն է։ մեծ տվյալների համար ուղարկեք հղում REST/gRPC ռեսուրսի կամ chunk ֆայլերի վրա։ SSE-ի համար տեղափոխվող gzip-ը տեղին է, բայց հետևեք բուֆերիզացիային 2019/CDN-ում։
7) Մեծացումը և ֆան-աուտը
7. 1 Հորիզոնական մեծացում
Դիմումը պահեք առանց վերագործարկումների։ Բնակավայրի վիճակը առջևի շերտում է։ տվյալները բրոկերից են։
Sticky (session/user) անհրաժեշտ է, եթե տեղական գծեր կան։
Իդեալը stateless ճակատն է, հանգույցը միայն բազմաբնույթ է։ իրադարձությունները գալիս են ընդհանուր pub/sub։
7. 2 Pub/Sub և բրոկերներ
Լայն ֆան-աուտայի համար օգտագործեք Kafka/NATS/Redis Streams։
«Fanout Gateway» շերտը ստորագրվում է տեղանունների վրա և թակում է WS/SSE հաճախորդներին։
Օգտագործեք ուղղման բանալին (օրինակ ՝ «userId», «matchID») նոդների միջև բեռը հավասարակշռելու համար։
8) Արտադրողական դելիգները
8. 1 NGINX — WebSocket
nginx map $http_upgrade $connection_upgrade { default upgrade; '' close; }
server {
listen 443 ssl http2;
server_name ws. example. com;
location /ws {
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1. 1;
proxy_read_timeout 75s; # increase for long sessions proxy_send_timeout 15s;
proxy_pass http://ws-backend;
}
}
8. 2 NGINX - SSE (կարևոր է անջատել բուֆերիզացիան)
nginx location /events {
proxy_http_version 1. 1;
proxy_set_header Connection "";
proxy_buffering off; # is critical for proxy_cache off threads;
chunked_transfer_encoding on;
proxy_read_timeout 60m;
proxy_pass http://sse-backend;
}
8. 3 Kubernetes (Ingress Annotations, NGINX Ingress)
yaml metadata:
annotations:
nginx. ingress. kubernetes. io/proxy-read-timeout: "3600"
nginx. ingress. kubernetes. io/proxy-send-timeout: "3600"
nginx. ingress. kubernetes. io/enable-websocket: "true"
nginx. ingress. kubernetes. io/proxy-buffering: "off" # для SSE
9) Կոդի օրինակներ
9. 1 SSE հաճախորդ (զննարկիչ)
js const es = new EventSource("/events? channel=odds", { withCredentials: true });
es. addEventListener("message", (e) => {
const data = JSON. parse(e. data);
renderOdds(data);
});
es. addEventListener("error", () => {
//EventSource will reconnect itself; can be shown spinner
});
9. 2 SSE սերվերը (Node. js/Express)
js app. get('/events', (req, res) => {
res. writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
});
res. write ('retry: 3000\n\n') ;//3s backoff to client
const sub = subscribe(req. query. channel, (event) => {
res. write(`id: ${event. id}\n`);
res. write(`event: message\n`);
res. write(`data: ${JSON. stringify(event. payload)}\n\n`);
});
req. on('close', () => sub. unsubscribe());
});
9. 3 Black Socket հաճախորդը (զննարկիչ)
js const ws = new WebSocket("wss://ws. example. com/ws");
ws. onopen = () => ws. send(JSON. stringify({ type: "join", room: "chat-1" }));
ws. onmessage = (m) => handle(JSON. parse(m. data));
ws. onclose = () => scheduleReconnect();
10) Անվտանգություն և սահմանափակում
Rate limiting per-ը և per-օգտագործողը 'սահմանափակեք մուտքային հաղորդագրությունների հաճախությունը (WS) և ելքային հոսքի արագությունը (WS/SSE)։
Delta-ը միավորման կյանքի ընթացքում և ընդհանուր օպտիկան է։
Message size limit и max messages/sec.
WAF/բոտ ֆիլտրերը Handsheika-ի փուլում։ պաշտպանություն connational flooding (շատ կարճ ձիեր)։
Tenault/namespace-ի մեկուսացումը ռեսուրսների առանձին փամփուշտներ է։
11) Դիտողականությունը
Մետրիկները
`connections_active`, `connections_new_total`, `bytes_in/out`,
`messages_in/out_total`, `dropped_messages_total`,
`reconnects_total`, `latency_delivery_ms{p50,p95,p99}`.
Լոգները ՝ IP/UA, userID/tenantID, փակման պատճառը («close _ code»), տևողությունը։
Թրեյսինգ 'կապեք իրադարձությունները ռուսական թիմի հետ (հարաբերական ID); WS-ի համար օգտագործեք «վիրտուալ» քնած։
12) Գործառնական նրբերանգներ
TFC տերմինալը ավելի մոտ է հաճախորդին (CDN/edge)։
Ակտիվ լուծարումը (graceful), երբ դուք տեսնում եք, որ դրոշը տալիս եք «փոխպատվաստում»։
Շարդինգը բանալին է, որպեսզի հավասարապես բաժանենք «տաք» ալիքները։
Վերջին բաժանորդների համար վիճակի նկարները (wwww.apshot + www.ta)։
Վերջին արժեքը (SSE հատկապես) օգտակար է «սառը» հաճախորդի համար։
13) Anti-patterna
Մեծ երկուական կտորների հոսքը SSE-ի կամ JSON-ի միջոցով WS-ի միջոցով, օգտագործեք HTTP-ի բեռնումը և հղումը խմբագրության մեջ։
Հեղինակային իրավունքը միայն կապի պահին և փետուրի ստուգումների բացակայությունը երկար պայմանագրերի վրա։
Համաշխարհային sticky-ը առանց ռուսական անհավասարակշռության և «տաք» նոդայի կարիքների։
Անջատված թայմաուտները/լիմիթները, որոնք կախված են ձիերից, ուտում են փամփուշտը։
Buferization SSE 71/CDN-ը «իրական ժամանակը» վերածվում է հետաձգման րոպեների։
Sequence/www.set-ի բացակայությունը reconn.ru-ից հետո հաճախորդը կորցնում է տվյալների ամբողջականությունը։
14) Ներդրման չեկի ցուցակ
- Ընտրվել է մոդել 'WS (երկբևեռ) կամ SSE (միակողմանի)։
- Timauts, keepalive և reconn.ru (backoff + jitter)։
- Նախագծված է sequence/www.set և (SSE-ի համար) 'id '/« Last-Event-ID »։
- Սահմանվում են սահմանները 'չափսը/արագությունը/կապը/քվոտան, պաշտպանությունը DoS-ից։
- George 07/ingrade: upgrade, proxy _ buffering off (SSE), read/send timeouts։
- Լայնացում ՝ pub/sub-broker, fan-aut-lace, sticky միայն անհրաժեշտության դեպքում։
- Վավերացում 'հոսանքի անվտանգ փոխանցում, նավարկություն առանց բեկման։
- Դիտարկումը 'չափումներ, լույսեր, հետքեր; dashbords ants.
- Օրինագծերի պլանը 'graceful-international- ը, հաճախորդի ազդանշանը փետուրի կապի մասին։
- Game Days: Ցանցի բեկորներ, նոդայի անկում, բրոքերի գերհագեցած, երկար RTT։
15) FAQ
Կարո՞ ղ եք կանխել SSE-ը CDN-ի միջոցով։
Սովորաբար ոչ, սա անհատականացված հոսք է։ Հանրային ջրանցքների համար հնարավոր է կարճ TTL և chunked-medivery, բայց հեշտ է կոտրել «իրական ժամանակը»։
Արդյո՞ ք Socket-ն աշխատում է HTTP/2/3-ի վերևում։
Զննարկիչ WS սկսում է HTTP/1-ից։ 1-upgrade; Կա RFC 8441 h2-ի համար, աջակցությունը 2019/սերվերում պահանջվում է առանձին։ H3-ից շարժման մեջ; H3-ում սթրիմինգի համար կա Express Transport, բայց սա մեկ այլ API-ն է։
GRPC vs WS-ի համար։
Մաքուր զննարկիչը չի ասում gRPC; անհրաժեշտ է GRPC-Web Envoy-ի միջոցով։ Ինտերակտիվ UI-ի համար հաճախ ավելի հեշտ է WS + REST-ը։
16) Արդյունքները
Socket-ը, երբ իրական ժամանակում երկխոսություն է անհրաժեշտ և կոմպակտ երկբևեռ ջրանցք։
SSE-ը, երբ անհրաժեշտ է պարզ և հուսալի push սերվերից հաճախորդին, նվազագույն բարդությունը և ավտոմատ reconnations-ը։
Վաճառքի հաջողությունը ճիշտ թայմաուտներ և լիմիտներ են, վերականգնումը www.set, pub/sub-fan-aut, ճիշտ պարամետրեր և հստակ դիտարկումը։