एचटीटीपी अनुरोध और जवाब है। रियल-टाइम उत्पादों को सर्वर को अगले पोल का इंतज़ार किए बिना धक्का देने की ज़रूरत होती है: चैट, लाइव डैशबोर्ड, मल्टीप्लेयर स्टेट, ट्रेडिंग टिक, सहयोगी कर्सर। वेबसॉकेट एक ही टीसीपी कनेक्शन पर लंबी-जीवित, फुल-डुप्लेक्स चैनल देते हैं। मुश्किल एक सॉकेट खोलना नहीं है। मुश्किल है नेटवर्क कट, ऑथ खत्म होना, और मल्टी-पॉड डिप्लॉय के नीचे हज़ारों सॉकेट को ईमानदार रखना।
यह प्रोडक्शन चेकलिस्ट है जो मुझे तब चाहिए थी जब पहली बार एक "सरल लाइव फीड" लोड बैलेंसर और मोबाइल क्लाइंट से टकराई।
वेबसॉकेट कब कमाते हैं अपना खर्च
| तरीका | सर्वर पुश | ओवरहेड | सबसे अच्छा उपयोग |
|---|---|---|---|
| शॉर्ट पोलिंग | नहीं (क्लाइंट पूछता है) | ऊँची अनुरोध दर, खाली २०० | दुर्लभ अपडेट, सरल कैश |
| लॉन्ग पोलिंग | लगभग | हर इंतज़ार पर रोका एचटीटीपी अनुरोध | जब वेबसॉकेट ब्लॉक हो तो फ़ॉलबैक |
| सर्वर-सेंट इवेंट्स (एसएसई) | एक तरफ़ा (सर्वर → क्लाइंट) | हल्का, एचटीटीपी-मित्र | फीड, नोटिफ़िकेशन |
| वेबसॉकेट | फुल डुप्लेक्स | एक कनेक्शन, फ़्रेम | चैट, गेम, दो-तरफ़ा कंट्रोल |
| वेबआरटीसी डेटा | पीयर-टू-पीयर | आइस/नैट जटिलता | मीडिया, सीधे पीयर ऐप |
वेबसॉकेट तब इस्तेमाल करें जब दोनों तरफ़ अक्सर भेजें, या जब लेटेंसी कम और स्थिर रखनी हो। एक-तरफ़ा स्ट्रीम के लिए एसएसई चुनें अगर उसी चैनल पर क्लाइंट→सर्वर की ज़रूरत नहीं। पुश न चाहने वाली रिक्वेस्ट/रिस्पॉन्स एपीआई के लिए सादा एचटीटीपी रखें।
हैंडशेक: एचटीटीपी जो सॉकेट बन जाता है
वेबसॉकेट सामान्य एचटीटीपी अनुरोध से शुरू होता है, अपग्रेड हेडर के साथ। ब्राउज़र (या क्लाइंट लाइब्रेरी) कुछ ऐसा भेजता है:
GET /ws HTTP/1.1
Host: api.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://app.example.com
अगर सर्वर स्वीकार करे, जवाब:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
उस 101 के बाद वही टीसीपी कनेक्शन वेबसॉकेट फ़्रेम ढोता है, एचटीटीपी बॉडी नहीं। मुख्य बातें:
१. Sec-WebSocket-Key / Accept: एन्क्रिप्शन नहीं। क्लाइंट नॉन्स चुनता है; सर्वर उसे स्थिर जीयूआईडी से हैश करता है (आरएफसी ६४५५)। दोनों पक्ष प्रोटोकॉल बोलते हैं, यही साबित होता है, और बेवकूफ प्रॉक्सी के आकस्मिक अपग्रेड रुकते हैं।
२. Origin: ब्राउज़र भेजते हैं। कुकी-प्रमाणित ऐप में सर्वर पर जाँचें ताकि कोई अजनबी साइट यूज़र के रूप में सॉकेट न खोले।
३. पाथ और क्वेरी: हैंडशेक पर रूटिंग और (सावधानी से) ऑथ के लिए उपलब्ध। एंडपॉइंट चुनने के लिए पाथ बेहतर (/ws/chat बनाम /ws/prices)।
४. सबप्रोटोकॉल: Sec-WebSocket-Protocol नामित ऐप प्रोटोकॉल तय करने देता है। एक होस्ट पर अलग मैसेज स्कीमा वाले कई क्लाइंट हों तो उपयोगी।
रिवर्स प्रॉक्सी को अपग्रेड अनुमति देनी चाहिए। एनजीनक्स पर अक्सर proxy_http_version 1.1, Upgrade और Connection पास करना, और लंबे (या बंद) आइडल टाइमआउट चाहिए। क्लाउड एलबी पर वेबसॉकेट समर्थन और आइडल टाइमआउट देखें; ६० सेकंड पर काटना यादृच्छिक डिस्कनेक्ट जैसा लगता है।
फ़्रेम, संदेश, और आप क्या भेजें
तार पर फ़्रेम हैं: टेक्स्ट, बाइनरी, पिंग, पोंग, क्लोज़। ऐप आमतौर पर संदेश देखती है (जोड़े गए फ़्रेम)। कॉन्ट्रैक्ट सादा रखें:
- नियंत्रण और छोटे पेलोड के लिए जेएसओएन टेक्स्ट (चैट, उपस्थिति)।
- आकार या पार्स लागत मायने रखे तो बाइनरी (प्रोटोबफ़, मैसेजपैक, फ्लैटबफ़र्स)।
- एक संदेश लिफ़ाफ़ा:
{ "type": "...", "id": "...", "payload": ... }ताकि हर क्लाइंट तोड़े बिना टाइप जोड़ सकें।
क्लोज़ कोड और कारण तय करें। 1000 सामान्य है। ऑथ विफलता, नीति-बाहर निकालना, सर्वर रीस्टार्ट अलग कोड रखें ताकि क्लाइंट जाने: रीकनेक्ट, फिर लॉगिन, या रुकना।
सॉकेट को अनलिमिटेड आरपीसी बस न समझें। संदेश आकार सीमित करें। दुरुपयोग पर अस्वीकार या बंद करें। बैकप्रेशर लगाएँ: क्लाइंट धीमा हो और सेंड बफ़र बढ़े तो गैर-ज़रूरी अपडेट गिराएँ या डिस्कनेक्ट करें, प्रक्रिया का ओओएम न करें।
हार्टबीट: मरे हुए और चुप को अलग करना
लैपटॉप स्लीप, नैट टाइमआउट, या केबल खिंचने के बाद टीसीपी लंबे समय हाफ़-ओपन रह सकता है। ऐप-स्तरीय जीवित-जाँच के बिना सर्वर अब भी यूज़र को ऑनलाइन मानता है।
पिंग / पोंग
आरएफसी ६४५५ नियंत्रण फ़्रेम पिंग और पोंग परिभाषित करता है। सर्वर या क्लाइंट पिंग भेजते हैं; पीयर को पोंग देना चाहिए। कई लाइब्रेरी इसे अंतराल विकल्प देते हैं।
व्यावहारिक शुरुआती मान:
| सेटिंग | सामान्य सीमा | नोट |
|---|---|---|
| पिंग अंतराल | १५से-३०से | ट्रेडिंग यूआई के लिए छोटा; बैटरी के लिए लंबा |
| पोंग टाइमआउट | पिंग के बाद ५से-१५से | पोंग न मिले → बंद कर संसाधन मुक्त |
| आइडल टाइमआउट | एलबी से जुड़ा | पिंग अंतराल से बड़ा होना चाहिए |
अगर लोड बैलेंसर ६० सेकंड पर आइडल कनेक्शन काटे, पिंग अंतराल स्पष्ट रूप से नीचे हो (जैसे २०से-३०से)। हार्टबीट रास्ता गर्म रखते हैं और साबित करते हैं कि ऐप परत अभी जवाब देती है।
ऐप-स्तरीय हार्टबीट
कुछ स्टैक छोटा ऐप संदेश भी भेजते हैं ({"type":"ping"}) ताकि सिर्फ़ एचटीटीपी समझने वाले मिडलबॉक्स कंट्रोल फ़्रेम न उलझाएँ, और मेट्रिक में आरटीटी माप सकें। लाइब्रेरी समर्थन करे तो प्रोटोकॉल पिंग बेहतर; कस्टम पेलोड या प्रॉक्सी कंट्रोल फ़्रेम बिगाड़े तो ऐप पिंग।
क्लोज़ पर (साफ़ या टाइमआउट), उपस्थिति अपडेट करें, उस कनेक्शन की सर्वर सब्सक्रिप्शन रद्द करें, मेमोरी मुक्त करें। लीक "ऑनलाइन" यूज़र वेबसॉकेट का क्लासिक प्रोडक्ट बग है।
रीकनेक्ट: क्लाइंट गिरेंगे, योजना बनाएँ
मोबाइल नेटवर्क सेल बदलते हैं। डिप्लॉय पॉड रीस्टार्ट करते हैं। लोग लैपटॉप बंद करते हैं। रीकनेक्ट किनारा नहीं; टिकाऊ क्लाइंट का मुख्य लूप है।
जिटर के साथ एक्सपोनेंशियल बैकऑफ़
हर क्लोज़ पर तुरंत रीकनेक्ट डिप्लॉय के बाद सर्वर पर तूफ़ान लाता है:
all clients reconnect at T+0 → thundering herd
बेहतर पैटर्न:
delay = min(cap, base * 2^attempt) * (0.5 + random())
उदाहरण: आधार 1s, सीमा 30s, पूरा जिटर। प्रयास ० लगभग ०.५से-१से प्रतीक्षा। बाद के प्रयास फैलते हैं। प्रयास काउंटर सिर्फ़ स्थिर ओपन के बाद रीसेट करें (जैसे १० सेकंड बिना त्रुटि), पहले onopen पर नहीं।
रीकनेक्ट के बाद क्या फिर सिंक करें
नए सॉकेट को छूटे इवेंट की याद नहीं। आम पैटर्न:
१. अंतिम इवेंट आईडी / कर्सर: क्लाइंट अंतिम लागू अनुक्रम या टाइमस्टैम्प रखे; ओपन के बाद पहला संदेश SUBSCRIBE + since।
२. स्नैपशॉट फिर डेल्टा: सर्वर वर्तमान स्टेट भेजे, फिर लाइव अपडेट। डैशबोर्ड के लिए सरल; बड़े स्टेट पर भारी।
३. संस्करणित रूम: क्लाइंट roomVersion रखे; पुराना हो तो पूरा रीसिंक।
इनमें से एक के बिना हर कट के बाद यूज़र गैप देखता है।
रीज़्यूम टोकन (वैकल्पिक)
कुछ सिस्टम यूज़र और स्ट्रीम ऑफ़सेट से बँधा छोटा-जीवित रीज़्यूम टोकन बनाते हैं। रीकनेक्ट पर टोकन दिखाकर पूरा री-ऑथ छोड़ें और ऑफ़सेट से जारी रखें। टोकन को क्रेडेंशियल जैसे मानें: छोटा टीटीएल, रोटेट, लॉगआउट पर रद्द।
वे क्लोज़ कारण जहाँ रीकनेक्ट न करें
| क्लोज़ का अर्थ | क्लाइंट कार्रवाई |
|---|---|
| सामान्य बंद / लॉगआउट | बंद रहें |
| ऑथ अमान्य / मना | फिर लॉगिन, फिर खोलें |
| रेट लिमिट / नीति | कड़ा बैकऑफ़, शायद रुकें |
| सर्वर रीस्टार्ट / आइडल टाइमआउट | बैकऑफ़ से रीकनेक्ट |
क्लोज़ कोड (और अपने ऐप त्रुटि संदेश) पार्स करें ताकि बैन पर हमेशा न घूमें।
ऑथ: इस सॉकेट पर कौन है?
हैंडशेक मुख्य द्वार है। 101 के बाद कई सर्वर टोकन के सत्र-मध्य खत्म होने तक पहचान फिर नहीं जाँचते।
काम करने वाले पैटर्न
| पैटर्न | कैसे | फ़ायदा | नुकसान |
|---|---|---|---|
| कुकी सेशन | अपग्रेड पर सेम-साइट कुकी | परिचित वेब ऑथ; ओरिजिन जाँच ज़रूरी | नेटिव/मोबाइल कठिन; कुकी डोमेन |
| क्वेरी टोकन | wss://host/ws?token=... |
ब्राउज़र WebSocket एपीआई में आसान |
लॉग, प्रॉक्सी, रेफ़रर इतिहास में टोकन |
| पहले संदेश पर ऑथ | अज्ञात कनेक्ट, फिर {"type":"auth","token":"..."} |
यूआरएल में टोकन नहीं | थोड़ी बिना-ऑथ खिड़की |
| सेक-वेबसॉकेट-प्रोटोकॉल तरकीब | प्रोटोकॉल हेडर में टोकन | क्वेरी स्ट्रिंग बचती है | सबप्रोटोकॉल का गैर-मानक उपयोग |
मेमोरी में बियरर रखने वाले एसपीए के लिए कस्टम क्लाइंट से Authorization या पहले संदेश पर ऑथ चुनें। एचटीटीपी-ओनली कुकी वाली फ़र्स्ट-पार्टी ब्राउज़र ऐप के लिए कुकी + सख्त ओरिजिन जाँच साफ़ है।
लंबे-जीवित रहस्य क्वेरी स्ट्रिंग में कभी न डालें। क्वेरी परम मजबूर हो (कुछ वातावरण) तो एचटीटीपी एपीआई से छोटा-जीवित, एक-बार वेबसॉकेट टिकट बनाएँ और पुन: उपयोग अस्वीकार करें।
कनेक्शन के बीच टोकन खत्म होना
एक्सेस टोकन सॉकेट खुला रहते खत्म होते हैं। विकल्प:
१. खत्म होने पर ऑथ कोड से बंद; क्लाइंट एचटीटीपी टोकन रिफ़्रेश कर रीकनेक्ट करे। २. सॉकेट पर रिफ़्रेश: क्लाइंट नया एक्सेस टोकन भेजे; सर्वर फिर सत्यापित कर जारी रखे। ३. सर्वर-साइड सेशन: हैंडशेक लंबी सर्वर सेशन बनाए; एक्सेस टोकन सिर्फ़ खोलते समय।
चैट ऐप के लिए विकल्प २ सहज। सुरक्षा समीक्षा में विकल्प १ आसान। दोनों में दस्तावेज़ लिखें; मिनट १५ पर खामोश मौत सपोर्ट टिकट फैक्ट्री है।
प्रमाणीकरण के बाद प्राधिकरण
ऑथएन "कौन" है। ऑथजेड "कौन से रूम/चैनल"। SUBSCRIBE channel:X पर एसीएल फिर जाँचें। रीकनेक्ट पर फिर जाँचें। क्लाइंट दिए रूम आईडी पर आँख मूँद भरोसा न करें। मल्टी-टेनेंट उत्पादों में हर सब्सक्रिप्शन को सत्यापित टोकन के टेनेंट आईडी से बाँधें, संदेश बॉडी से नहीं।
एक प्रक्रिया से आगे स्केल
एक नोड या गो प्रक्रिया कई कनेक्शन रख सकती है, लेकिन:
- डिप्लॉय और क्रैश सब गिरा देते हैं।
- जेएसओएन फैन-आउट पर सीपीयू अक्सर रैम से पहले सीमा बनती है।
- पॉड १ पर यूज़र ए को पॉड २ की सिर्फ़-मेमोरी प्रकाशित संदेश नहीं मिलता।
स्टिकी सेशन काफी नहीं
लोड बैलेंसर क्लाइंट को एक पॉड पर पिन कर सकते हैं (कुकी या आईपी)। इससे एक यूज़र के इन-मेमोरी कनेक्शन मैप में मदद मिलती है, लेकिन यह हल नहीं करता: "संदेश पॉड ए पर बना, उपभोक्ता पॉड बी पर जुड़ा।" कोई भी ब्रॉडकास्ट या क्रॉस-यूज़र इवेंट साझा बस चाहता है।
पब/सब फैन-आउट
मानक आकार:
Client ←→ WS gateway pod ←→ Redis (or NATS, Kafka, etc.) ←→ other gateway pods
↑
app workers / API
१. क्लाइंट किसी भी गेटवे पॉड से जुड़ता है; पॉड स्थानीय कॉन → यूज़र/रूम दर्ज करता है।
२. कुछ होने पर (एपीआई लिखना, वर्कर जॉब) चैनल पर प्रकाशित करें: room:42, user:7, tenant:acme:alerts।
३. उस चैनल की सदस्य हर गेटवे पॉड इवेंट पाती है और सिर्फ़ स्थानीय मेल खाते सॉकेट पर लिखती है।
क्षणिक फैन-आउट के लिए रेडिस पब/सब आम है। रिटेंशन और कंज़्यूमर ग्रुप हों तो रेडिस स्ट्रीम्स या काफ़्का। कम लेटेंसी आंतरिक मैसेजिंग के लिए नैट्स लोकप्रिय। ब्रांड नहीं, टिकाऊपन की ज़रूरत से चुनें।
क्षैतिज चिंताएँ
| चिंता | तरीका |
|---|---|
| कनेक्शन संख्या | कई छोटे गेटवे पॉड; खुले सॉकेट + सीपीयू पर ऑटोस्केल |
| गरम रूम | रूम आईडी से शार्ड; एक प्रक्रिया अकेले सेलिब्रिटी चैनल न रखे |
| क्रमबद्ध डिलीवरी | प्रति-रूम अनुक्रम; क्लाइंट छाँटे या पुराना गिराए |
| कम-से-कम-एक-बार | क्लाइंट इवेंट आईडी से डी-डुप |
| सुंदर ड्रेन | नए स्वीकार बंद, क्लोज़ का इंतज़ार या "रीकनेक्ट" से ज़बरदस्ती, पब/सब से अनरजिस्टर |
| अवलोकन | मेट्रिक: खुले कॉन, छूटे पिंग, सेंड कतार गहराई, पब/सब लैग, ऑथ विफलता |
स्टेटफुल अतिरिक्त
उपस्थिति ("कौन ऑनलाइन") और टाइपिंग संकेतक छोटे टीटीएल और हार्टबीट चाहते हैं, अक्सर रेडिस में। एक से अधिक पॉड ट्रैफ़िक दे तो उपस्थिति सिर्फ़ प्रक्रिया मेमोरी में न रखें।
बड़े बाइनरी ब्लास्ट (फ़ाइल चंक, वीडियो) आमतौर पर नियंत्रण चैट वाले उसी सॉकेट पर नहीं। अलग चैनल या ऑब्जेक्ट स्टोरेज + साइन किए यूआरएल।
न्यूनतम सर्वर स्केच (मानसिक मॉडल)
स्यूडोकोड, फ़्रेमवर्क नहीं:
on HTTP upgrade:
user = authenticate(request)
if not user: reject 401
if not origin_allowed(request): reject 403
socket = accept()
register(socket, user)
subscribe_bus(user.rooms)
on message(socket, msg):
if msg.type == "subscribe":
if authorize(user, msg.room): add_local(socket, msg.room); bus_sub(msg.room)
elif msg.type == "publish":
if authorize(...): bus_publish(msg.room, envelope(msg))
on bus_event(room, event):
for socket in local_sockets(room):
try send(socket, event) except backpressure: drop_or_close
on ping timeout / close:
unregister(socket)
update_presence(user)
महत्वपूर्ण विभाजन: गेटवे पर स्थानीय सॉकेट मैप, क्रॉस-पॉड डिलीवरी के लिए साझा बस, हर विशेषाधिकार बदलाव पर ऑथ।
क्लाइंट चेकलिस्ट
१. प्रोडक्शन में wss:// से खोलें (टीएलएस)।
२. एलबी आइडल टाइमआउट से नीचे हार्टबीट (प्रोटोकॉल या ऐप)।
३. एक्सपोनेंशियल बैकऑफ़ + जिटर से रीकनेक्ट।
४. अंतिम इवेंट आईडी या स्नैपशॉट से रीज़्यूम।
५. अनंत रीकनेक्ट लूप के बिना ऑथ खत्म होना संभालें।
६. आने वाले संदेश आकार सीमित करें और स्कीमा सत्यापित करें।
७. यूआई में कनेक्शन स्थिति दिखाएँ (ऑनलाइन / रीकनेक्टिंग / ऑफ़लाइन)।
८. पेज छिपने / ऐप बैकग्राउंड पर तय करें सॉकेट रखें या रोकें (मोबाइल बैटरी)।
आम विफलता मोड
| लक्षण | संभावित कारण |
|---|---|
| हर ~६०से यादृच्छिक डिस्कनेक्ट | प्रॉक्सी आइडल टाइमआउट; हार्टबीट बहुत धीमे |
| एक सर्वर पर ठीक, मल्टी-पॉड पर खामोश चूक | पब/सब नहीं; सिर्फ़ मेमोरी |
| डिप्लॉय के बाद रीकनेक्ट तूफ़ान | बैकऑफ़/जिटर नहीं; ड्रेन नहीं |
| एक्सेस लॉग में टोकन | क्वेरी-स्ट्रिंग ऑथ |
| "ऑनलाइन" भूत | पोंग टाइमआउट नहीं; उपस्थिति साफ़ नहीं |
| गेटवे पर ओओएम | अनलिमिटेड सेंड बफ़र; बैकप्रेशर नहीं |
| सीएसआरएफ-जैसा हाईजैक | ओरिजिन जाँच के बिना कुकी ऑथ |
वेबसॉकेट कब न इस्तेमाल करें
- मुख्यतः रिक्वेस्ट/रिस्पॉन्स सीआरयूडी, दुर्लभ अपडेट: एचटीटीपी सरल है।
- उस एचटीटीपी इन्फ़्रा पर एक-तरफ़ा सर्वर पुश जिस पर पहले से भरोसा: एसएसई काफ़ी हो सकता है।
- एक जैसे सार्वजनिक डेटा का विशाल फैन-आउट: सीडीएन + एसएसई या कैश एज पर पोलिंग सस्ता पड़ सकता है।
- छोटी अनुरोध आयु वाली सर्वरलेस प्लेटफ़ॉर्म बिना सॉकेट समर्थन: प्रबंधित रियल-टाइम सेवा या लंबी-चलने वाली गेटवे परत।
वेबसॉकेट एक ट्रांसपोर्ट है। वे ऑथ डिज़ाइन, आइडेम्पोटेंट इवेंट आईडी, या मल्टी-नोड फैन-आउट की योजना की जगह नहीं लेते। हैंडशेक सही करें, हार्टबीट से जीवित साबित करें, धैर्य से रीकनेक्ट करें, हर सब्सक्रिप्शन पर द्वार रखें, और पॉड के बीच बस लगाएँ। बाकी उस कनेक्शन पर प्रोडक्ट पॉलिश है जो बना रहता है।
