OpenAI मोठ्या प्रमाणावर कमी-लेटन्सी व्हॉइस AI कसे वितरित करते
Yi Zhang आणि William McDonald, तांत्रिक कर्मचारी सदस्य यांच्याद्वारे
संभाषण बोलण्याच्या गतीनेच पुढे जात असेल तरच व्हॉइस AI नैसर्गिक वाटते. जेव्हा नेटवर्क त्यात अडथळा आणते, तेव्हा लोकांना ते लगेचच विचित्र विराम, व्यत्यय किंवा उशिरा केलेला हस्तक्षेप म्हणून जाणवते. ही गोष्ट ChatGPT व्हॉइससाठी, रिअलटाइम API वापरून बिल्ड करणाऱ्या डेव्हलपर्ससाठी, इंटरॅक्टिव्ह वर्कफ्लोमध्ये काम करणाऱ्या एजंट्ससाठी आणि वापरकर्ता बोलत असतानाच ऑडिओवर प्रक्रिया करण्याची गरज असलेल्या मॉडेल्ससाठी महत्त्वाची आहे.
OpenAI च्या व्याप्तीनुसार, त्यातून तीन ठोस आवश्यकता निर्माण होतात:
- आठवड्याला 900 दशलक्षाहून अधिक सक्रिय वापरकर्त्यांसाठी जागतिक पोहोच
- जलद कनेक्शन सेटअप, जेणेकरून सेशन सुरू होताच वापरकर्ता बोलायला सुरुवात करू शकेल
- कमी आणि स्थिर मीडिया राऊंड-ट्रिप टाइम, कमी जिटर आणि पॅकेट लॉसमुळे, संवादातील प्रतिसाद स्पष्ट आणि सहज वाटतो
रिअल-टाइम AI इंटरॅक्शन्ससाठी जबाबदार असलेल्या OpenAI मधील टीमने अलीकडेच आमच्या WebRTC स्टॅकची पुनर्रचना केली आहे, जेणेकरून मोठ्या प्रमाणावर काम करताना एकमेकांसमोर येणाऱ्या तीन मर्यादांचे निराकरण करता येईल: एका सेशनसाठी एक-पोर्ट मीडिया टर्मिनेशन हे OpenAI च्या पायाभूत सुविधांमध्ये योग्य बसत नाही, स्टेटफुल ICE (इंटरऍक्टिव्ह कनेक्टिव्हिटी एस्टॅब्लिशमेंट) आणि DTLS (डेटाग्राम ट्रान्सपोर्ट लेयर सिक्युरिटी) सेशन्ससाठी स्थिर मालकीची आवश्यकता असते, आणि ग्लोबल राउटिंगमध्ये फर्स्ट-हॉप लेटन्सी कमी ठेवावी लागते. या पोस्टमध्ये, आम्ही तयार केलेल्या स्प्लिट रिले प्लस ट्रान्सीव्हर आर्किटेक्चरची माहिती देणार आहोत, जे क्लायंटसाठी मानक WebRTC कार्यप्रणाली कायम ठेवते आणि त्याच वेळी OpenAI च्या इन्फ्रास्ट्रक्चरमध्ये पॅकेट्सच्या राउटिंगची पद्धत बदलते.
WebRTC हे ब्राउझर, मोबाईल ॲप्स आणि सर्व्हर यांच्यामध्ये कमी-लेटन्सी असलेले ऑडिओ, व्हिडिओ आणि डेटा पाठवण्यासाठी एक खुले मानक आहे. हे सहसा पीअर-टू-पीअर कॉलिंगशी जोडले जाते, परंतु ते क्लायंट-टू-सर्व्हर रिअल-टाइम सिस्टीमसाठी एक व्यावहारिक पाया देखील आहे, कारण ते इंटरॲक्टिव्ह मीडियाच्या कठीण भागांचे मानकीकरण करते: कनेक्टिव्हिटी स्थापित करण्यासाठी आणि NAT (नेटवर्क ॲड्रेस ट्रान्सलेशन) ट्रॅव्हर्सलसाठी ICE, एनक्रिप्टेड ट्रान्सपोर्टसाठी DTLS आणि SRTP (सिक्युअर रिअल-टाइम ट्रान्सपोर्ट प्रोटोकॉल), ऑडिओ कॉम्प्रेस आणि डीकोड करण्यासाठी कोडेक नेगोशिएशन, गुणवत्ता नियंत्रणासाठी RTCP (रिअल-टाइम ट्रान्सपोर्ट कंट्रोल प्रोटोकॉल), आणि इको कॅन्सलेशन व जिटर बफरिंग यांसारखी क्लायंट-साइड वैशिष्ट्ये.
AI उत्पादनांसाठी मानकीकरण महत्त्वाचे आहे. WebRTC शिवाय, प्रत्येक क्लायंटला NAT ओलांडून कनेक्टिव्हिटी कशी स्थापित करावी, मीडिया एन्क्रिप्ट कसा करावा, कोडेक्सवर (प्रसारण आणि डीकंप्रेशनसाठी निवडलेले कोडर-डीकोडर) वाटाघाटी कशा कराव्यात आणि बदलत्या नेटवर्क परिस्थितीशी जुळवून कसे घ्यावे, यासाठी वेगवेगळे उत्तर द्यावे लागले असते. WebRTC मुळे, आम्ही ब्राउझर्स आणि मोबाइल प्लॅटफॉर्मवर आधीच लागू केलेल्या प्रोटोकॉल स्टॅकवर काम करू शकतो, आणि आमचे स्वतःचे काम रिअल-टाइम मीडियाला मॉडेल्सशी जोडणाऱ्या इन्फ्रास्ट्रक्चरवर केंद्रित करू शकतो.
आम्ही WebRTC इकोसिस्टमवरच आधारित काम करतो, ज्यामध्ये परिपक्व ओपन-सोर्स अंमलबजावणी आणि ब्राउझर, मोबाइल ॲप्स व सर्व्हर यांना परस्परांशी सुसंगत ठेवणारे मानक कार्य समाविष्ट आहे. Justin Uberti (WebRTC च्या मूळ आर्किटेक्टपैकी एक) आणि Sean DuBois (Pion चे निर्माते आणि देखभालकर्ते) यांच्या पायाभूत कार्यामुळे आमच्यासारख्या टीम्सना निम्न-स्तरीय ट्रान्सपोर्ट, एन्क्रिप्शन आणि गर्दी-नियंत्रण कार्यप्रणाली नव्याने तयार करण्याऐवजी, सिद्ध झालेल्या मीडिया इन्फ्रास्ट्रक्चरवर काम करणे शक्य झाले. आम्ही भाग्यवान आहोत की Justin आणि Sean दोघेही आता OpenAI मध्ये आमचे सहकारी आहेत, जे WebRTC आणि रिअल-टाइम AI यांना अधिक जवळ आणण्यासाठी मार्गदर्शन करत आहेत.
AI साठी ऑडिओ सतत स्ट्रीमच्या स्वरूपात येणे ही सर्वात महत्त्वाची बाब आहे. त्यामुळे स्पोकन एजंट वापरकर्ता बोलत असतानाच ट्रान्सक्राइब करणे, रीझनिंग, टूल्स वापरणे किंवा आवाज तयार करणे सुरू करू शकतो, पूर्ण अपलोडची वाट पाहावी लागत नाही. हाच फरक नैसर्गिक संभाषणासारखी वाटणारी प्रणाली आणि फक्त बटण दाबून बोलण्यासारखी वाटणारी प्रणाली यांच्यात निर्माण करतो.
एकदा आम्ही WebRTC निवडल्यावर, पुढचा प्रश्न होता की ते कोठे समाप्त करायचे (WebRTC कनेक्शन आम्ही कोठे स्वीकारून त्याची मालकी घेऊ—उदाहरणार्थ, एजवर) आणि ते सेशन्स इन्फरन्स बॅकएंडशी कसे जोडायचे. टर्मिनेशन महत्त्वाचे आहे कारण त्यावरच ठरते की आपण रिअल-टाइम सेशन स्टेट, मीडिया ट्रान्सपोर्ट, राउटिंग, लेटन्सी आणि फेल्युअर आयसोलेशन कसे हाताळतो.
SFU, किंवा निवडक फॉरवर्डिंग युनिट, हा असा मीडिया सर्व्हर आहे जो प्रत्येक सहभागीकडून एक WebRTC स्ट्रीम प्राप्त करतो आणि इतरांना निवडकपणे स्ट्रीम फॉरवर्ड करतो. या मॉडेलमध्ये, SFU प्रत्येक सहभागीसाठी स्वतंत्र WebRTC कनेक्शन टर्मिनेट करते, आणि AI सत्रात आणखी एक सहभागी म्हणून सामील होते. ग्रुप कॉल्स, वर्गखोल्या किंवा सहयोगी मीटिंग्ज यांसारख्या मुळातच बहु-सहभागी असलेल्या उत्पादनांसाठी हे योग्य ठरू शकते. हे ऑडिओ कोडेक्स, RTCP संदेश, डेटा चॅनेल्स, रेकॉर्डिंग आणि प्रति-स्ट्रीम धोरण एकाच ठिकाणी ठेवते.1
क्लायंट-टू-AI उत्पादनांमध्येही, SFU हा अनेकदा डीफॉल्ट सुरुवातीचा बिंदू असतो, कारण तो संघांना सिग्नलिंग, मीडिया रूटिंग, रेकॉर्डिंग, निरीक्षणक्षमता आणि भविष्यातील विस्तारांसाठी—जसे की मानवी हस्तांतरण किंवा अधिक सहभागी जोडणे—एकच सिद्ध प्रणाली पुन्हा वापरण्याची परवानगी देतो.
आमचा कार्यभार वेगळा आहे. बहुतेक सत्रे 1:1 असतात—एक वापरकर्ता एका मॉडेलशी बोलतो, किंवा एक ॲप्लिकेशन एका रिअल-टाइम एजंटशी बोलते—आणि प्रत्येक टप्प्यावर विलंबाबाबत संवेदनशीलता असते. अशा प्रकारच्या ट्रॅफिकसाठी, आम्ही ट्रान्ससीव्हर मॉडेल निवडले: WebRTC एज सेवा क्लायंट कनेक्शन टर्मिनेट करते आणि नंतर मीडिया व इव्हेंट्सना मॉडेल इन्फरन्स, लिप्यंतरण, वाणी निर्मिती, साधन वापर आणि ऑर्केस्ट्रेशनसाठी सोप्या अंतर्गत प्रोटोकॉलमध्ये रूपांतरित करते.
या डिझाइनमध्ये, ट्रान्ससीव्हर ही WebRTC सत्र स्थितीची मालकी राखणारी एकमेव सेवा आहे, ज्यामध्ये ICE कनेक्टिव्हिटी तपासण्या, DTLS हँडशेक, SRTP एन्क्रिप्शन की आणि सत्र लाइफसायकल यांचा समावेश होतो. येथे “टर्मिनेशन” म्हणजे ट्रान्ससीव्हर हा असा एंडपॉइंट आहे, जो हे हँडशेक पूर्ण करतो आणि मीडिया एन्क्रिप्ट किंवा डिक्रिप्ट करतो. ही स्थिती एका ठिकाणी ठेवल्यामुळे सत्राची मालकी समजून घेणे सोपे झाले, आणि त्यामुळे बॅकएंड सेवा स्वतः WebRTC पीअर म्हणून वागण्याऐवजी सामान्य सेवांसारख्या स्केल होऊ शकल्या.
ट्रान्ससीव्हर मॉडेल निवडल्यानंतर, आमची पहिली अंमलबजावणी Pion वर तयार केलेली एकच Go सेवा होती, जी सिग्नलिंग आणि मीडिया टर्मिनेशन दोन्ही हाताळत होती. याच्यावर ChatGPT व्हॉइस, Realtime API चा WebRTC एंडपॉइंट आणि अनेक संशोधन प्रकल्प चालतात.
कार्यात्मकदृष्ट्या, ट्रान्ससीव्हर सेवा दोन कार्ये करते:
- सिग्नलिंग: SDP नेगोशिएशन, कोडेक निवड, ICE क्रेडेन्शियल्स आणि सत्र सेटअप
- मीडिया: डाउनस्ट्रीम WebRTC कनेक्शन समाप्त करणे आणि इन्फरन्स व ऑर्केस्ट्रेशनसाठी बॅकएंड सेवांशी अपस्ट्रीम कनेक्शन कायम ठेवणे
आम्हाला ही सेवा आमच्या उर्वरित इन्फ्रास्ट्रक्चरप्रमाणे चालवायची होती: Kubernetes वर, जिथे मागणी बदलत असताना वर्कलोड्स स्केल होऊ शकतात आणि होस्ट्सदरम्यान हलू शकतात. परंतु पारंपरिक प्रत्येक-सत्रासाठी-एक-पोर्ट WebRTC मॉडेल त्या वातावरणाशी नीट जुळत नाही, कारण ते मोठ्या सार्वजनिक UDP पोर्ट श्रेणींवर अवलंबून असते, ज्या pods जोडले, काढले किंवा पुन्हा शेड्यूल केले जात असताना उघड करणे, सुरक्षित करणे आणि कायम ठेवणे कठीण असते.2
पहिली समस्या म्हणजे प्रत्येक सत्रासाठी एक पोर्ट असलेले मॉडेल स्वतःच होते. उच्च समांतरतेच्या परिस्थितीत, याचा अर्थ खूप मोठ्या UDP पोर्ट श्रेणींचे उघडणे आणि व्यवस्थापन करणे असा होतो.
- क्लाउड लोड बॅलन्सर्स आणि Kubernetes सेवा प्रत्येक सेवेसाठी दहा हजारोंच्या संख्येतील सार्वजनिक UDP पोर्ट्स लक्षात घेऊन डिझाइन केलेल्या नसतात. प्रत्येक अतिरिक्त श्रेणीमुळे लोड बॅलन्सर कॉन्फिगरेशन, हेल्थ तपासणी, फायरवॉल धोरण आणि रोलआउट सुरक्षितता यांमध्ये परिचालनात्मक गुंतागुंत वाढते.3
- मोठ्या UDP पोर्ट श्रेणी सुरक्षित करणे कठीण असते, कारण त्या बाहेरून पोहोचता येणारे क्षेत्र वाढवतात आणि नेटवर्क धोरणाचे ऑडिट करणे अधिक कठीण बनवतात.
- ते autoscaling साठीही योग्य बसत नाहीत. Kubernetes मध्ये पॉड्स सतत जोडले जातात, काढले जातात आणि पुन्हा शेड्यूल केले जातात. प्रत्येक पॉडने मोठी स्थिर पोर्ट श्रेणी राखीव ठेवणे आणि जाहीर करणे आवश्यक केल्यास ती लवचिकता नाजूक बनते.4
म्हणूनच अनेक WebRTC प्रणाली प्रत्येक सर्व्हरसाठी एकाच UDP पोर्टकडे वळतात, आणि त्या पोर्टच्या मागे अनुप्रयोग-स्तरावरील डीमल्टिप्लेक्सिंग करतात.5
प्रत्येक सर्व्हरसाठी एकच पोर्ट असलेल्या डिझाइन्स पोर्टची संख्या हा प्रश्न सोडवतात, परंतु त्या दुसरी समस्या निर्माण करतात: संपूर्ण फ्लीटमध्ये प्रत्येक सत्राचे मालकी हक्क राखणे.
ICE आणि DTLS हे स्थिती राखणारे प्रोटोकॉल आहेत. ज्या प्रक्रियेने एखादे सत्र तयार केले आहे, त्या प्रक्रियेला त्या सत्राची पॅकेट्स सतत मिळत राहणे आवश्यक असते, जेणेकरून ती कनेक्टिव्हिटी तपासण्या सत्यापित करू शकेल, DTLS हँडशेक पूर्ण करू शकेल, SRTP डिक्रिप्ट करू शकेल आणि ICE रीस्टार्ट्ससारखे नंतरचे सत्र बदल प्रक्रिया करू शकेल. जर त्याच सत्राची पॅकेट्स वेगळ्या प्रक्रियेकडे पोहोचली, तर सेटअप अयशस्वी होऊ शकतो किंवा मीडिया खंडित होऊ शकतो.
त्यामुळे आम्हाला एक विशिष्ट लक्ष्य मिळाले: सार्वजनिक इंटरनेटवर एक लहान, निश्चित UDP पृष्ठभाग उघड करणे, आणि तरीही प्रत्येक पॅकेट संबंधित WebRTC सत्र असलेल्या ट्रान्ससीव्हरकडे रूट करणे.
ते साध्य करण्यासाठी आम्ही अनेक मार्गांचे मूल्यांकन केले, ज्यात TURN (Traversal Using Relays around NAT) समाविष्ट आहे, जिथे एज रिले क्लायंट अलोकेशन्स संपुष्टात आणतो आणि त्यांच्या वतीने ट्रॅफिक फॉरवर्ड करतो.2
पद्धत | फायदे | तोटे |
प्रत्येक सेशनसाठी युनिक IP:पोर्ट (याला नेटिव्ह डायरेक्ट UDP असेही म्हणतात) | थेट क्लायंट-टू-सर्व्हर मीडिया मार्ग डेटा मार्गात कोणताही फॉरवर्डिंग लेयर नाही | प्रत्येक सेशनसाठी एका सार्वजनिक UDP पोर्टची आवश्यकता असते मोठ्या पोर्ट रेंज उघड करणे आणि सुरक्षित करणे कठीण असते Kubernetes आणि क्लाउड लोड बॅलेंसरसाठी योग्य नाही |
प्रत्येक सर्व्हरसाठी युनिक IP:पोर्ट | प्रति सेशन एक्सपोजरपेक्षा खूपच लहान सार्वजनिक UDP फूटप्रिंट प्रति सर्व्हर एक सामायिक सॉकेट अनेक सेशन्सना डिमल्टीप्लेक्स करू शकते | एकाच होस्टवर व्यवस्थित काम करते, परंतु शेअर्ड लोड-बॅलन्स्ड फ्लीटवर स्वतःहून काम करत नाही एकाच होस्टवर सेशन डिमल्टीप्लेक्सिंग तेव्हाच मदत करते जेव्हा पॅकेट त्या होस्टवर पोहोचते; लोड-बॅलन्स्ड फ्लीटवर, पहिले पॅकेट तरीही चुकीच्या इन्स्टन्सवर पोहोचू शकते, त्यामुळे प्रत्येक सेशनला त्याच्या मालकीच्या प्रोसेसकडे निर्देशित करण्यासाठी तुम्हाला एका निश्चित पद्धतीची आवश्यकता असते |
TURN रिले (प्रोटोकॉल-समाप्त करणारा) | क्लायंटना फक्त TURN रिले अड्रेस आणि पोर्टपर्यंत पोहोचणे आवश्यक असते धोरण एजवर केंद्रीत करता येते | TURN ॲलोकेशन्समुळे सेटअप राऊंड ट्रिप्स वाढतात TURN सर्व्हर्समध्ये ॲलोकेशन्स हलवणे किंवा परत मिळवणे अजूनही अवघड आहे |
स्टेटलेस फॉरवर्डर + स्टेटफुल टर्मिनेटर (OpenAI चे रिले + ट्रान्सीव्हर) | लहान सार्वजनिक UDP फूटप्रिंट संपूर्ण WebRTC सेशनची मालकी अजूनही ट्रान्सीव्हरकडेच असते | मीडिया मालकीच्या ट्रान्सीव्हरपर्यंत पोहोचण्यापूर्वी एक फॉरवर्डिंग हॉप जोडते रिले आणि ट्रान्सीव्हरमध्ये विशेष समन्वयाची आवश्यकता असते |
आम्ही रिलीज केलेली आर्किटेक्चर पॅकेट रूटिंगला प्रोटोकॉल टर्मिनेशनपासून वेगळे करते. सत्र सेटअपसाठी सिग्नलिंग अजूनही ट्रान्ससीव्हरपर्यंत पोहोचते, तर मीडिया प्रथम रिलेच्या माध्यमातून प्रवेश करते. रिले हा लहान सार्वजनिक फूटप्रिंट असलेला हलका UDP फॉरवर्डिंग लेयर आहे, आणि ट्रान्ससीव्हर हा त्याच्या मागे असलेला स्टेटफुल WebRTC एंडपॉइंट आहे.
रिले मीडिया डिक्रिप्ट करत नाही, ICE स्टेट मशीन्स चालवत नाही किंवा कोडेक नेगोशिएशनमध्ये सहभागी होत नाही. गंतव्य निवडण्यासाठी ते पुरेसा पॅकेट मेटाडेटा वाचते आणि नंतर पॅकेट त्या सत्राचा मालक असलेल्या ट्रान्ससीव्हरकडे फॉरवर्ड करते. ट्रान्ससीव्हरला अजूनही सामान्य WebRTC फ्लो दिसतो आणि सर्व प्रोटोकॉल स्थितीची जबाबदारी त्याच्याकडेच राहते. क्लायंटच्या दृष्टीकोनातून, WebRTC सत्राबद्दल काहीही बदलत नाही.
या सेटअपमध्ये पहिल्या-पॅकेटचे रूटिंग ही महत्त्वाची पायरी आहे. पॅकेट मार्गावर कोणतेही सत्र अस्तित्वात येण्यापूर्वी, रिलेने क्लायंटकडून आलेले पहिले पॅकेट बाह्य लुकअप सेवेवर थांबून न राहता पॅकेट मार्गावरच रूट करणे आवश्यक असते.
प्रत्येक WebRTC सत्रात आधीपासूनच प्रोटोकॉलमध्ये अंगभूत रूटिंग हुक असतो: ICE username fragment, किंवा ufrag, हा सत्र सेटअपदरम्यान देवाणघेवाण केला जाणारा आणि STUN कनेक्टिव्हिटी तपासण्यांमध्ये परत पाठवला जाणारा एक छोटा ओळखकर्ता असतो. आम्ही सर्व्हर-साइड ufrag तयार करतो, जेणेकरून त्यात रिलेने गंतव्य क्लस्टर आणि मालकीचा ट्रान्ससीव्हर ओळखण्यासाठी पुरेसा एवढाच रूटिंग मेटाडेटा असेल.
सिग्नलिंगदरम्यान, ट्रान्ससीव्हर सत्र स्थिती वाटप करतो आणि SDP उत्तरामध्ये शेअर केलेला रिले VIP आणि UDP पोर्ट परत करतो. VIP हा रिले फ्लीटच्या पुढे असलेला व्हर्च्युअल IP पत्ता असतो; पोर्टसह एकत्रितपणे, तो क्लायंटला `203.0.113.10:3478` सारखे एकच स्थिर गंतव्य देतो, जरी त्यामागे अनेक रिले इन्स्टन्स असले तरीही. क्लायंटचे पहिले मीडिया-पाथ पॅकेट सहसा STUN (Session Traversal Utilities for NAT) बाइंडिंग विनंती असते, जी जाहिरात केलेल्या पत्त्यापर्यंत पॅकेट्स पोहोचू शकतात की नाही हे पडताळण्यासाठी ICE वापरते.
रिले पहिल्या STUN पॅकेटचे फक्त आवश्यक तेवढेच पार्स करते, जेणेकरून सर्व्हर ufrag वाचता येईल, routing hint डीकोड करता येईल, आणि पॅकेट मालकीच्या ट्रान्ससीव्हरकडे फॉरवर्ड करता येईल. प्रत्येक ट्रान्ससीव्हर सामायिक UDP सॉकेटवर ऐकतो, म्हणजे अंतर्गत IP:port ला बांधलेला एक ऑपरेटिंग सिस्टम एंडपॉइंट, प्रत्येक सत्रासाठी स्वतंत्र सॉकेट नव्हे. रिलेने क्लायंटच्या स्रोत IP:port पासून त्या ट्रान्ससीव्हर गंतव्यापर्यंत सत्र तयार केल्यानंतर, पुढील DTLS, RTP आणि RTCP पॅकेट्स ufrag पुन्हा डीकोड न करता सत्रामध्ये वाहतात.
रिलेचे सत्र मुद्दाम किमान ठेवलेले असते, ज्यामध्ये पॅकेट फॉरवर्डिंगसाठी माहिती देणारे फक्त इन-मेमरी सत्र, तसेच मॉनिटरिंगसाठी आवश्यक काउंटर आणि सत्र कालबाह्यता व क्लीनअपसाठी टाइमर असतात. या डिझाइनमुळे पॅकेट रूटिंग थेट पॅकेट मार्गावरच राखले जाते. जर रिले रीस्टार्ट झाले आणि सत्र गमावले, तर पुढील STUN पॅकेट ufrag रूटिंग संकेतावरून सत्र पुन्हा तयार करते. हे अधिक विश्वसनीय बनवण्यासाठी, मार्ग स्थापित झाल्यावर <क्लायंट IP + पोर्ट, ट्रान्ससीव्हर IP + पोर्ट> चे मॅपिंग Redis कॅशेमध्ये ठेवले जाते, जेणेकरून पुढील STUN पॅकेट येण्यापूर्वीच ते पुनर्प्राप्त करता येईल.
एकदा आम्ही सार्वजनिक UDP पृष्ठभाग स्थिर पत्ते आणि पोर्ट्स यांच्या छोट्या संख्येपर्यंत कमी केल्यावर, आम्ही तोच रिले नमुना जागतिक स्तरावर लागू करू शकलो. Global Relay हा आमचा भौगोलिकदृष्ट्या वितरित रिले प्रवेश बिंदूंचा समूह आहे, जे सर्व समान पॅकेट-फॉरवर्डिंग वर्तन लागू करतात.
व्यापक भौगोलिक इनग्रेसमुळे क्लायंटपासून OpenAI पर्यंतचा पहिला हॉप कमी होतो, कारण पॅकेटला प्रथम दूरच्या प्रदेशापर्यंत सार्वजनिक इंटरनेट ओलांडून जाण्याऐवजी, भौगोलिकदृष्ट्या आणि नेटवर्क टोपोलॉजीच्या दृष्टीने वापरकर्त्याच्या जवळ असलेल्या रिलेद्वारे आमच्या नेटवर्कमध्ये प्रवेश करता येतो. व्यावहारिक भाषेत, याचा अर्थ ट्रॅफिक आमच्या बॅकबोनपर्यंत पोहोचण्यापूर्वी कमी विलंब, कमी जिटर आणि टाळता येण्याजोग्या लॉस बर्स्ट्सची कमी संख्या असा होतो.6
आम्ही सिग्नलिंगसाठी Cloudflare चे भौगोलिक आणि निकटता-आधारित स्टीयरिंग वापरतो, त्यामुळे प्रारंभिक HTTP किंवा WebSocket विनंती जवळच्या ट्रान्ससीव्हर क्लस्टरपर्यंत पोहोचते. विनंतीचा संदर्भ सत्राचे स्थान आणि क्लायंटला कोणता Global Relay इनग्रेस पॉइंट सांगितला जाईल हे निर्धारित करतो. SDP उत्तर Global Relay पत्ता प्रदान करते, तर ufrag मध्ये Global Relay ला मीडिया निर्धारित क्लस्टरकडे रूट करण्यासाठी आणि relay ला गंतव्य ट्रान्ससीव्हरकडे रूट करण्यासाठी पुरेशी माहिती असते.
एकत्रितपणे, भू-मार्गित सिग्नलिंग आणि Global Relay सेटअप आणि मीडिया दोन्ही जवळच्या प्रवेश मार्गावर ठेवतात, तसेच सत्र एका ट्रान्ससीव्हरशी अँकर करतात. यामुळे सिग्नलिंगसाठी आणि पहिल्या ICE कनेक्टिव्हिटी तपासणीसाठी लागणारा राउंड-ट्रिप वेळ कमी होतो, ज्यामुळे वापरकर्त्याला बोलणे सुरू होण्यापूर्वी प्रतीक्षा करावी लागणारा वेळ कमी होतो.
आम्ही रिले सेवा Go मध्ये लिहिली आणि अंमलबजावणी मुद्दाम मर्यादित ठेवली. Linux वर, कर्नलचा नेटवर्किंग स्टॅक मशीनच्या नेटवर्क इंटरफेसकडून UDP पॅकेट्स प्राप्त करतो आणि ती सॉकेटकडे वितरित करतो—म्हणजेच एखादी प्रक्रिया IP:Port ला बाइंड केल्यानंतर ज्या ऑपरेटिंग सिस्टम एंडपॉइंटवरून वाचते तो एंडपॉइंट. Relay यूजरस्पेसमध्ये चालतो, त्यामुळे नियमित Go प्रक्रिया त्या सॉकेटमधून पॅकेट हेडर्स वाचते, फ्लो स्टेटचा थोडासा भाग अपडेट करते आणि WebRTC समाप्त न करता पॅकेट्स फॉरवर्ड करते. आम्हाला कोणत्याही कर्नल-बायपास फ्रेमवर्कची गरज भासली नाही; असे फ्रेमवर्क यूजरस्पेस प्रक्रियेला जास्त पॅकेट दरांसाठी नेटवर्क क्यू थेट पोल करण्याची परवानगी देईल, पण त्याचबरोबर ऑपरेशनल गुंतागुंतही वाढवेल.
मुख्य डिझाइन निवडी:
- प्रोटोकॉल टर्मिनेशन नाही: रिले फक्त STUN headers/ufrag पार्स करते; ते पुढील DTLS, RTP आणि RTCP साठी कॅश केलेली स्थिती वापरते, ज्यामुळे पॅकेट्स अपारदर्शक राहतात.
- तात्पुरती स्थिती: फ्लो स्थिती आणि निरीक्षणक्षमतेसाठी, हे क्लायंट पत्त्याचा ट्रान्ससीव्हर गंतव्याशी संबंध दर्शवणारा एक लहान, अल्प-टाइमआउट असलेला, इन-मेमरी मॅप राखते.
- क्षैतिज स्केलेबिलिटी: लोड बॅलन्सरच्या मागे अनेक रिले इन्स्टन्सेस समांतर चालतात. स्टेट हे कठोर WebRTC स्टेट नसते, त्यामुळे रीस्टार्ट्समुळे ट्रॅफिकमध्ये अत्यल्प ड्रॉप्स होतात आणि फ्लो लवकर पुनर्प्राप्त होतो.
कार्यक्षमता उपाययोजना:
SO_REUSEPORTहा Linux सॉकेट पर्याय आहे जो त्याच मशीनवरील अनेक रिले वर्कर्सना तोच UDP पोर्ट बाइंड करण्याची परवानगी देतो. त्यानंतर कर्नल येणारी पॅकेट्स त्या वर्कर्समध्ये वितरित करतो, ज्यामुळे एकाच वाचन-लूपमुळे निर्माण होणारी अडचण टाळली जाते.runtime.LockOSThreadUDP वाचणाऱ्या प्रत्येक goroutine ला विशिष्ट OS थ्रेडला बांधून ठेवते.SO_REUSEPORTसोबत वापरल्यास, त्याच प्रवाहातील पॅकेट्स (स्रोत आणि गंतव्य IP:Port तसेच प्रोटोकॉल) त्याच CPU कोअरवर राहण्याची शक्यता वाढते, ज्यामुळे कॅश लोकॅलिटी सुधारते आणि कॉन्टेक्स्ट स्विचिंग कमी होते.- पूर्व-वाटप केलेले बफर्स आणि किमान कॉपी करणे यामुळे Go मध्ये गार्बेज कलेक्शन टाळण्यासाठी पार्सिंग आणि वाटप ओव्हरहेड कमी राहतो.
या अंमलबजावणीने तुलनेने लहान रिले फूटप्रिंटसह आमचा जागतिक रीयल-टाइम मीडिया ट्रॅफिक हाताळला, म्हणून आम्ही कर्नल बायपासचा मार्ग स्वीकारण्याऐवजी अधिक सोपी रचना कायम ठेवली.
ही आर्किटेक्चर आम्हाला हजारो UDP पोर्ट उघडे न करता Kubernetes मध्ये WebRTC मीडिया चालवू देते. हे महत्त्वाचे आहे, कारण लहान आणि निश्चित UDP एक्स्पोजरची व्याप्ती सुरक्षित करणे आणि लोड बॅलन्स करणे सोपे असते, तसेच मोठ्या सार्वजनिक पोर्ट श्रेणी राखून न ठेवता इन्फ्रास्ट्रक्चर स्केल करता येते. Kubernetes कडून मिळणाऱ्या अधिक चांगल्या इन्फ्रा सपोर्टमुळे आणि कमी उघड्या पृष्ठभागामुळे मिळणाऱ्या अधिक सुरक्षेमुळे, हे डिझाइन क्लायंटसाठी मानक WebRTC वर्तनही जपते आणि आमच्या वर्कलोडसाठी SFU-विरहित डिझाइन हाच योग्य डीफॉल्ट होता याची पुष्टी करते. आमची बहुतांश सेशन्स पॉइंट-टू-पॉइंट, विलंब-संवेदनशील आहेत आणि जेव्हा इन्फरन्स सेवांना WebRTC पीअर्ससारखे वागण्याची गरज नसते तेव्हा ती स्केल करणे अधिक सोपे होते.
यातील व्यापक धडा असा आहे की गुंतागुंत वाढवण्याचे सर्वोत्तम ठिकाण म्हणजे एक पातळ राउटिंग स्तर—प्रत्येक बॅकएंड सेवेमध्ये नाही, आणि सानुकूलित क्लायंट वर्तनामध्येही नाही. राउटिंग मेटाडेटा प्रोटोकॉल-नेटिव्ह फील्डमध्ये एन्कोड केल्यामुळे आम्हाला निर्धारक पहिल्या-पॅकेटचे राउटिंग, लहान सार्वजनिक UDP फूटप्रिंट, आणि जगभरातील वापरकर्त्यांच्या जवळ इनग्रेस ठेवण्यासाठी पुरेशी लवचिकता मिळाली.
काही निवडी विशेषतः महत्त्वाच्या होत्या:
- एजवर प्रोटोकॉलचे सेमॅंटिक्स जतन करा. क्लायंट्स अजूनही मानक WebRTC वापरतात, ज्यामुळे ब्राउझर आणि मोबाइल इंटरऑपरेबिलिटी अबाधित राहते.
- जटिल सत्र स्थिती एकाच ठिकाणी ठेवा. ट्रान्ससीव्हर ICE, DTLS, SRTP आणि सत्र जीवनचक्राचे व्यवस्थापन करतो; रिले फक्त पॅकेट्स पुढे पाठवतो.
- सेटअपमध्ये आधीपासून असलेल्या माहितीच्या आधारे रूट करा. हॉट-पाथ लुकअप अवलंबित्व न जोडता ICE ufrag ने आम्हाला पहिल्या-पॅकेटसाठी रूटिंग हुक दिला.
- कर्नल बायपास वापरण्यापूर्वी सामान्य प्रकरणासाठी ऑप्टिमाइझ करा.
SO_REUSEPORTचा काळजीपूर्वक वापर, थ्रेड पिनिंग आणि कमी-अलोकेशन पार्सिंग असलेली मर्यादित Go अंमलबजावणी आमच्या वर्कलोडसाठी पुरेशी ठरली.
रिअल-टाइम व्हॉइस AI तेव्हाच कार्य करते जेव्हा इन्फ्रास्ट्रक्चरमुळे विलंब जाणवू नये इतका अदृश्य वाटतो. आमच्यासाठी, याचा अर्थ WebRTC कडून क्लायंट्सना असलेल्या अपेक्षा न बदलता आमच्या WebRTC उपयोजनाची रचना बदलणे असा होता.
लेखक
References
1. How Discord Handles Two and Half Million Concurrent Voice Users using WebRTC(नवीन विंडोमध्ये उघडेल)
2. GitHub - l7mp/stunner: A Kubernetes media gateway for WebRTC(नवीन विंडोमध्ये उघडेल)
3. WebRTC Ports in a nutshell [Examples] - BlogGeek.me(नवीन विंडोमध्ये उघडेल)
4. Deploy to Kubernetes - LiveKit docs(नवीन विंडोमध्ये उघडेल)
6. Cloudflare Calls: millions of cascading trees all the way down(नवीन विंडोमध्ये उघडेल)


