- PHP में लॉन्ग पोलिंग HTTP अनुरोधों को खुला रखती है, जो सीमित PHP वर्करों को अवरुद्ध कर सकती है और यदि इसे सरल ब्लॉकिंग लूप के साथ लागू किया जाता है तो स्केलेबिलिटी को नुकसान पहुंचा सकती है।
- आधुनिक इवेंट-ड्रिवन दृष्टिकोण, सावधानीपूर्वक कॉन्फ़िगरेशन और बैचिंग, कैशिंग और रेट लिमिटिंग जैसे अनुकूलन कई लॉन्ग पोलिंग समस्याओं को कम कर सकते हैं।
- वेबसॉकेट, एसएसई और प्रबंधित रीयल-टाइम प्लेटफॉर्म जैसे विकल्प अक्सर उच्च-समवर्ती परिदृश्यों के लिए रॉ पीएचपी लॉन्ग पोलिंग की तुलना में बेहतर प्रदर्शन प्रदान करते हैं।
यदि आपने कभी किसी क्लासिक PHP ऐप में "रियल टाइम" व्यवहार को जोड़ने की कोशिश की है, तो संभवतः आप लॉन्ग पोलिंग और उससे जुड़ी अजीब प्रदर्शन समस्याओं से रूबरू हुए होंगे। HTTP अनुरोध को तब तक खुला रखना जब तक भेजने के लिए कुछ नया न हो - एक सरल सी तरकीब लगती है, लेकिन अचानक अवरुद्ध PHP प्रक्रियाओं, सर्वर मेमोरी, टाइमआउट और कुछ ही उपयोगकर्ताओं से आगे बढ़ने के तरीके के बारे में अजीब सवाल खड़े कर देती है।
यह गाइड PHP में लॉन्ग पोलिंग की समस्या, इसके व्यवहार के कारणों, वास्तव में मायने रखने वाली बाधाओं और उनसे निपटने के तरीकों के बारे में विस्तार से बताती है। हम जानेंगे कि मतदान प्रक्रिया कितनी लंबी है, और एक भोला-भाला व्यक्ति क्यों... sleep()PHP आधारित कार्यान्वयन अक्सर शॉर्ट पोलिंग से खराब होता है, आधुनिक इवेंट लूप और वेब सर्वर इसमें कैसे मदद कर सकते हैं, और कौन से ऑप्टिमाइज़ेशन प्रयास के लायक हैं। इस दौरान हम लॉन्ग पोलिंग की तुलना वेबसॉकेट और सर्वर-सेंट इवेंट्स से करेंगे, सुरक्षा और त्रुटि प्रबंधन पर चर्चा करेंगे, और यह देखेंगे कि आपको PHP को छोड़कर Node.js या किसी प्रबंधित रीयल-टाइम प्लेटफ़ॉर्म का उपयोग कब करना चाहिए।
लॉन्ग पोलिंग क्या है और यह वास्तव में कैसे काम करती है?
मूल रूप से, लॉन्ग पोलिंग HTTP ही है, जिसमें सर्वर जानबूझकर प्रतिक्रिया को तब तक विलंबित करता है जब तक कि उसके पास कहने के लिए कुछ दिलचस्प न हो। क्लाइंट द्वारा हर कुछ सेकंड में सर्वर से "क्या कुछ नया आया है?" पूछने के बजाय, क्लाइंट एक अनुरोध भेजता है जिसे सर्वर खुला रखता है, और केवल तभी जवाब देता है जब नया डेटा तैयार हो या टाइमआउट की अवधि समाप्त हो जाए।
सामान्य लंबी मतदान अनुरोध/प्रतिक्रिया चक्र कुछ इस प्रकार दिखता है: ब्राउज़र (या कोई भी क्लाइंट) एक विशेष एंडपॉइंट पर HTTP अनुरोध करता है, सर्वर अनुरोध स्वीकार करता है लेकिन तुरंत प्रतिक्रिया नहीं भेजता है, और सर्वर द्वारा नए इवेंट या डेटा की प्रतीक्षा करते समय TCP कनेक्शन खुला रहता है।
यदि कोई घटना घटती है - जैसे चैट संदेश, सूचना, गेम अपडेट - तो सर्वर तुरंत प्रतीक्षा कर रहे क्लाइंट को जवाब देता है। क्लाइंट उस पेलोड को प्रोसेस करता है और, सबसे महत्वपूर्ण बात यह है कि, तुरंत एक नया लॉन्ग पोलिंग अनुरोध भेजता है ताकि अगले अपडेट के लिए हमेशा (या लगभग हमेशा) एक खुला कनेक्शन मौजूद रहे।
यदि कुछ समय तक कुछ नहीं होता है, तो सर्वर अंततः एक निर्धारित समय सीमा के बाद अनुरोध को टाइम आउट कर देता है, और या तो खाली डेटा या "कोई अपडेट नहीं" पेलोड के साथ प्रतिक्रिया देता है। जब क्लाइंट को यह टाइमआउट प्रतिक्रिया मिलती है, तब भी वह एक नया अनुरोध भेजता है, जिससे एक अनंत कनेक्शन के बजाय बार-बार HTTP कॉल के माध्यम से दीर्घकालिक व्यवहार बना रहता है।
इसलिए, हालांकि लोग "लगातार" लॉन्ग पोलिंग कनेक्शन के बारे में बात करते हैं, तकनीकी रूप से यह एक कभी न खत्म होने वाली स्ट्रीम के बजाय काफी लंबे समय तक चलने वाले HTTP अनुरोधों का एक लूप है। यह सूक्ष्म अंतर PHP के लिए बहुत मायने रखता है, क्योंकि इनमें से प्रत्येक अनुरोध आमतौर पर अपने पूरे जीवनकाल के लिए एक ही PHP वर्कर प्रोसेस या थ्रेड से जुड़ा होता है।
PHP में लॉन्ग पोलिंग बनाम शॉर्ट पोलिंग
शॉर्ट पोलिंग एक सरल, पुराने जमाने का पैटर्न है: क्लाइंट एक निश्चित समय सारणी पर सर्वर से नया डेटा मांगता है और सर्वर तुरंत जवाब देता है। आप टकरा सकते हैं /notifications हर 3-5 सेकंड में डेटाबेस को जल्दी से जांचें और जो भी नया डेटा मिले उसे भेज दें।
यह दृष्टिकोण तर्कसंगत तो लगता है, लेकिन जब अधिकांश सर्वेक्षणों में "कुछ भी नया नहीं" सामने आता है तो यह बेहद व्यर्थ साबित होता है। आप लगातार आने वाले ज्यादातर खाली रिस्पॉन्स पर सीपीयू, डेटाबेस क्वेरी और नेटवर्क ओवरहेड खर्च करते हैं, और उपयोगकर्ता को अभी भी किसी घटना के घटित होने और अगले निर्धारित पोल के बीच देरी दिखाई दे सकती है।
लॉन्ग पोलिंग इस मॉडल को उलट देता है: HTTP अनुरोधों की संख्या कम होती है, लेकिन सर्वर किसी घटना की प्रतीक्षा करते हुए प्रत्येक अनुरोध बहुत लंबे समय तक बना रहता है। सैद्धांतिक रूप से, इससे HTTP ओवरहेड कम होता है और प्रतिक्रियाशीलता में सुधार होता है, क्योंकि उपयोगकर्ता अगले पोल अंतराल की प्रतीक्षा करने के बजाय जैसे ही अपडेट होते हैं, उन्हें प्राप्त हो जाते हैं।
PHP में दिक्कत यह है कि एक साधारण लॉन्ग पोलिंग एंडपॉइंट प्रतीक्षा की अवधि के लिए वर्कर को ब्लॉक कर देता है। यदि आप किसी लूप का उपयोग करके 300 सेकंड के लिए कनेक्शन खुला रखते हैं sleep()आप एक PHP प्रक्रिया या थ्रेड को व्यस्त कर रहे हैं जो अन्यथा उसी समय सीमा में कई त्वरित लघु-पोल अनुरोधों को पूरा कर सकता था।
लोड की स्थिति में दोनों की तुलना करने पर, खराब तरीके से लागू किया गया लॉन्ग पोलिंग एंडपॉइंट वास्तव में शॉर्ट पोलिंग की तुलना में बहुत कम समवर्ती क्लाइंट को संभाल सकता है। उदाहरण के लिए, एक PHP-FPM पूल जो हजारों छोटे 5-सेकंड के पोल को आसानी से संभाल सकता है, वह ठप हो सकता है यदि प्रत्येक उपयोगकर्ता एक समय में 300 सेकंड के लिए एक वर्कर का उपयोग करता है।
पीएचपी का क्लासिक लॉन्ग पोलिंग पैटर्न समस्याग्रस्त क्यों है?
लॉन्ग पोलिंग के लिए एक बहुत ही सामान्य PHP रेसिपी मोटे तौर पर "increase" जैसी दिखती है। max_execution_timeसेशन बंद करें, फिर लूप करें sleep() नए डेटा की जांच करते समय। सैद्धांतिक रूप से यह सीधा है: आप PHP को बहुत जल्दी टाइम आउट होने से रोकते हैं, सेशन लॉक को मुक्त करते हैं ताकि उसी उपयोगकर्ता के अन्य अनुरोध चल सकें, और फिर लगभग 300 सेकंड तक एक लूप में नए संदेशों के लिए पोलिंग करते हैं।
उस लूप के अंदर, आपका कोड संभवतः डेटाबेस से क्वेरी करें या प्रत्येक पुनरावृति पर कुछ इन-मेमोरी कैश का निरीक्षण करें, लगभग एक सेकंड के लिए रुकते हुए। sleep(1) बैकएंड पर अत्यधिक दबाव डालने से बचने के लिए। यदि आपको कोई नई सूचना मिलती है, तो आप लूप से बाहर निकल जाते हैं, प्रतिक्रिया भेजते हैं और स्क्रिप्ट समाप्त कर देते हैं; यदि नए डेटा के बिना समय सीमा समाप्त हो जाती है, तो आप एक खाली ऐरे या कोई "कोई अपडेट नहीं" मार्कर वापस भेज देते हैं।
क्लाइंट साइड पर, थोड़ा सा जावास्क्रिप्ट (आमतौर पर इसके माध्यम से) $.ajax() jQuery में या fetch() (वैनिला जेएस में) यह एंडपॉइंट बार-बार कॉल करता है। ब्राउज़र को जब भी कोई प्रतिक्रिया (डेटा या खाली) मिलती है, तो वह शायद कुछ सेकंड प्रतीक्षा करता है और फिर तुरंत एक और लॉन्ग पोल अनुरोध भेजता है, जो प्रभावी रूप से तब तक चलता रहता है जब तक उपयोगकर्ता पृष्ठ पर बना रहता है।
हालांकि यह पैटर्न कम उपयोगकर्ताओं के लिए काम करता है, लेकिन इसकी सीमाएं बहुत जल्दी सामने आ जाती हैं क्योंकि प्रत्येक प्रतीक्षा अनुरोध एक पूरे PHP वर्कर का उपयोग कर लेता है। अपाचे प्रीफोर्क या PHP-FPM सेटअप के साथ, प्रत्येक अवरुद्ध स्क्रिप्ट इंस्टेंस निष्क्रिय रहने के पूरे समय रैम और संसाधनों का उपयोग करता है, जिसका अर्थ है कि 30-40 समवर्ती क्लाइंट भी ध्यान देने योग्य हो सकते हैं, और सावधानीपूर्वक ट्यूनिंग के बिना 100 से अधिक क्लाइंट खतरनाक होने लगते हैं।
इससे भी बुरी बात यह है कि यह समझना आसान नहीं है कि क्या sleep() कॉल वास्तव में क्या कर रहा है? ऑपरेटिंग सिस्टम के दृष्टिकोण से, आपका PHP थ्रेड उस स्लीप के दौरान वास्तव में कुछ भी उत्पादक काम नहीं कर रहा होता है, फिर भी इसे एक लाइव वर्कर के रूप में गिना जाता है जिसे अन्य अनुरोधों के लिए पुन: उपयोग नहीं किया जा सकता है।
थ्रेड्स, प्रोसेस और वेब सर्वर मॉडल
PHP में लॉन्ग पोलिंग की समस्या को सही मायने में समझने के लिए, आपको यह देखना होगा कि आपका वेब सर्वर कनेक्शन और वर्कर प्रक्रियाओं को कैसे प्रबंधित करता है। परंपरागत अपाचे प्रीफोर्क कई प्रक्रियाओं को उत्पन्न करता है, जिनमें से प्रत्येक एक समय में एक अनुरोध को संभालती है; अन्य एमपीएम या पीएचपी-एफपीएम एक समान एक-अनुरोध-प्रति-कार्यकर्ता पैटर्न के साथ श्रमिकों के पूल का उपयोग करते हैं।
जब प्रत्येक लॉन्ग पोलिंग क्लाइंट किसी अनुरोध को मिनटों तक खुला रखता है, तो आप PHP वर्कर्स के उस सीमित पूल को जल्दी ही समाप्त कर देते हैं। उनमें से प्रत्येक ज्यादातर निष्क्रिय पड़ा रहता है, मेमोरी को अवरुद्ध करता है और एक बार जब आप कॉन्फ़िगर की गई अधिकतम सीमा तक पहुँच जाते हैं तो आगे के किसी भी ट्रैफ़िक को सेवा देने से रोकता है।
इसकी तुलना उन प्रणालियों से करें जो नॉन-ब्लॉकिंग I/O और इवेंट लूप के इर्द-गिर्द बनी हैं, जहां एक सिंगल OS थ्रेड हजारों समवर्ती कनेक्शनों को संभाल सकता है, बशर्ते उनमें से अधिकांश निष्क्रिय हों। उस दुनिया में, ऑपरेटिंग सिस्टम स्टैक के अंदर "कुछ" वास्तव में प्रतीक्षा कर रहा होता है, लेकिन यह प्रति कनेक्शन एक भारी-भरकम यूजरलैंड प्रक्रिया नहीं होती है।
HTTP के संदर्भ में Nginx एक अच्छा उदाहरण है: यह बहुत कम मेमोरी ओवरहेड के साथ बड़ी संख्या में खुले कनेक्शनों को प्रबंधित करने के लिए एक इवेंट-ड्रिवन आर्किटेक्चर का उपयोग करता है। जब आप FastCGI या PHP-FPM के माध्यम से PHP को Nginx से जोड़ते हैं, तो Nginx क्लाइंट कनेक्शन को चालू रख सकता है और अनुरोधों को PHP वर्करों के एक निश्चित आकार के पूल में वितरित कर सकता है, जिससे कुछ राहत मिलती है लेकिन यह अवरुद्ध PHP स्क्रिप्ट को जादुई रूप से ठीक नहीं करता है।
यही कारण है कि "प्रत्येक लॉन्ग पोल एक थ्रेड को ब्लॉक करता है" जैसा सरल मंत्र अति सरलीकरण है, लेकिन फिर भी कई क्लासिक PHP डिप्लॉयमेंट के लिए यह बेहद सटीक है। जब तक आप किसी अतुल्यकालिक रनटाइम या किसी भिन्न आर्किटेक्चर का उपयोग नहीं करते हैं, तब तक एक सामान्य PHP स्क्रिप्ट तुल्यकालिक रूप से निष्पादित होती है और जब तक वह मौजूद रहती है तब तक एक वर्कर को व्यस्त रखती है।
क्या Node.js वाकई में यहाँ कुछ खास है?
Node.js को अक्सर एक जादुई समाधान के रूप में उद्धृत किया जाता है क्योंकि यह डिफ़ॉल्ट रूप से सिंगल-थ्रेडेड इवेंट लूप और नॉन-ब्लॉकिंग I/O का उपयोग करता है। प्रत्येक कनेक्शन के लिए एक थ्रेड बनाने के बजाय, नोड एक साथ कई खुले सॉकेटों पर नज़र रखता है और डेटा आने या कोई घटना घटित होने पर ही वास्तविक कार्य करता है।
इस वास्तुशिल्पीय विकल्प से मामूली हार्डवेयर पर बड़ी संख्या में निष्क्रिय लॉन्ग पोलिंग या वेबसॉकेट कनेक्शनों का समर्थन करना कहीं अधिक आसान हो जाता है। जब कोई संदेश प्रवाहित नहीं हो रहा होता है, तो नोड का इवेंट लूप अभी भी सक्रिय रहता है लेकिन मुश्किल से काम कर रहा होता है, और प्रति कनेक्शन रैम का उपयोग क्लासिक पीएचपी वर्कर-प्रति-अनुरोध सेटअप की तुलना में बहुत कम होता है।
हालांकि, PHP इस मामले में पूरी तरह से बाहर नहीं है; इसमें आधुनिक इवेंट लूप लाइब्रेरी भी हैं जो समान नॉन-ब्लॉकिंग व्यवहार प्रदान करती हैं। ReactPHP, Amp या Revolt जैसे प्रोजेक्ट आपको PHP के अंदर एक इवेंट-ड्रिवन रनटाइम देते हैं, जो प्रत्येक कनेक्शन के लिए एक ब्लॉकिंग वर्कर को स्पिन अप किए बिना सॉकेट या अतुल्यकालिक कार्यों को प्रबंधित कर सकता है।
हालांकि, व्यवहार में, अधिकांश पुराने PHP एप्लिकेशन अभी भी Apache या PHP-FPM के साथ एक सिंक्रोनस मॉडल पर चल रहे हैं और उनमें कोई इवेंट लूप नहीं है। उन ऐप्स के लिए, "नोड लॉन्ग पोलिंग में बेहतर है" वाली धारणा काफी हद तक सही है, क्योंकि तुलनीय स्केलेबिलिटी प्राप्त करने के लिए आपको अपने PHP स्टैक को काफी हद तक फिर से डिज़ाइन करना होगा।
वेबसॉकेट और एसएसई की तुलना में पोलिंग कितनी लंबी है?
लॉन्ग पोलिंग सर्वर से क्लाइंट तक डेटा भेजने का सिर्फ एक तरीका है; वेबसॉकेट और सर्वर-सेंट इवेंट्स (एसएसई) अक्सर आधुनिक रीयल-टाइम ऐप्स के लिए बेहतर विकल्प होते हैं। प्रत्येक तकनीक की अपनी जटिलता, क्षमता और संसाधन खपत के संदर्भ में कुछ कमियां और खूबियां होती हैं।
वेबसॉकेट एक ही उन्नत टीसीपी कनेक्शन पर क्लाइंट और सर्वर के बीच एक सच्चा द्विदिशात्मक चैनल स्थापित करता है। एक बार अपग्रेड प्रक्रिया पूरी हो जाने के बाद, दोनों पक्ष HTTP हेडर की अनावश्यक प्रक्रिया को दोहराए बिना इच्छानुसार संदेश भेज सकते हैं, जो चैट ऐप्स, मल्टीप्लेयर गेम्स, डैशबोर्ड और बार-बार अपडेट होने वाले किसी भी परिदृश्य के लिए एक बहुत बड़ा लाभ है।
दूसरी ओर, एसएसई एक लंबे समय तक चलने वाले एचटीटीपी कनेक्शन पर सर्वर से क्लाइंट तक घटनाओं की एकतरफा धारा प्रदान करता है। यह नोटिफिकेशन, लाइव फीड या किसी भी ऐसे मामले के लिए उपयुक्त है जहां केवल सर्वर को डेटा भेजने की आवश्यकता होती है और क्लाइंट प्रारंभिक अनुरोध के अलावा शायद ही कभी कोई जानकारी वापस भेजता है।
लॉन्ग पोलिंग इन दोनों के बीच में कहीं आती है: यह बार-बार HTTP अनुरोधों का उपयोग करके सर्वर पुश का अनुकरण करती है, इसलिए आपको हर बार कनेक्शन और हेडर ओवरहेड का भुगतान करना पड़ता है। इसका फायदा यह है कि यह अतिरिक्त प्रोटोकॉल या विशेष क्लाइंट समर्थन के बिना सामान्य HTTP इन्फ्रास्ट्रक्चर और मानक ब्राउज़रों के साथ काम करता है।
Socket.IO जैसी कई रीयल-टाइम लाइब्रेरी वास्तव में लॉन्ग पोलिंग से शुरू होती हैं और फिर जब संभव हो तो वेबसॉकेट में अपग्रेड हो जाती हैं, लॉन्ग पोलिंग को प्राथमिक तंत्र के बजाय बैकअप के रूप में मानती हैं। इससे आपको बड़े पैमाने पर लंबी अवधि के मतदान की सापेक्षिक दक्षता के बारे में बहुत कुछ पता चलता है।
लंबे समय तक मतदान करने वाले एंडपॉइंट्स के लिए सुरक्षा संबंधी विचार
हालांकि लॉन्ग पोलिंग एक निम्न-स्तरीय प्लंबिंग डिटेल की तरह प्रतीत होती है, फिर भी प्रत्येक लॉन्ग पोलिंग एंडपॉइंट केवल एक HTTP API सतह है जिसे ठीक से सुरक्षित किया जाना चाहिए। पहला, अपरिवर्तनीय कदम यह है कि इसे विशेष रूप से HTTPS पर ही उपलब्ध कराया जाए ताकि आवागमन के दौरान ट्रैफिक को रोका या उसमें छेड़छाड़ न की जा सके।
परिवहन सुरक्षा के अलावा, आपको सभी लॉन्ग पोलिंग अनुरोधों के लिए सख्त प्रमाणीकरण और प्राधिकरण की आवश्यकता होती है। चाहे आप सेशन कुकीज़, JWT, API टोकन या OAuth का उपयोग करें, सर्वर को यह सत्यापित करना होगा कि प्रत्येक खुला कनेक्शन एक वैध उपयोगकर्ता से मेल खाता है और उपयोगकर्ता को अनुरोधित डेटा स्ट्रीम प्राप्त करने की अनुमति है।
कुछ क्लासिक ब्राउज़र सुरक्षा संबंधी चिंताएं, जैसे कि सीएसआरएफ, कम प्रासंगिक हो सकती हैं यदि आप मानक फॉर्म से निहित कुकी-आधारित प्रमाणीकरण पर निर्भर नहीं हैं, लेकिन फिर भी आपको अपने विशिष्ट संदर्भ के बारे में सोचने की आवश्यकता है। यदि कुकीज़ शामिल हैं या यदि एंडपॉइंट स्थिति में परिवर्तन ला सकता है, तो एंटी-सीएसआरएफ सुरक्षा (टोकन, समान-साइट कुकीज़, आदि) महत्वपूर्ण बनी रहती हैं।
इनपुट वैलिडेशन लॉन्ग पोलिंग के लिए उतना ही महत्वपूर्ण है जितना कि किसी अन्य HTTP API के लिए। SQL इंजेक्शन, पाथ ट्रैवर्सल या लॉजिक बग से बचने के लिए चैनल आइडेंटिफायर, यूजर आईडी, फिल्टर या टाइमस्टैम्प जैसे पैरामीटर को सर्वर पर सैनिटाइज और वैलिडेट किया जाना चाहिए, जिससे यूजर्स के बीच डेटा लीक हो सकता है।
लॉन्ग पोलिंग से डिनायल-ऑफ-सर्विस परिदृश्यों का भी द्वार खुल जाता है क्योंकि PHP में कनेक्शन जानबूझकर लंबे समय तक चलने वाले और अपेक्षाकृत महंगे होते हैं। आपको प्रति आईपी या प्रति खाते के हिसाब से उचित दर सीमा लागू करनी चाहिए, एक साथ होने वाले कनेक्शनों की संख्या सीमित करनी चाहिए और संसाधनों के उपयोग को नियंत्रण में रखने के लिए कनेक्शन टाइमआउट लागू करना चाहिए।
निरंतर निगरानी, लॉगिंग और आवधिक सुरक्षा ऑडिट सुरक्षा की अंतिम परत हैं। लॉन्ग पोलिंग त्रुटियों, प्रमाणीकरण विफलताओं और असामान्य कनेक्शन पैटर्न को लॉग करने से आपको वह डेटा मिलता है जिसकी आपको वास्तविक ट्रैफ़िक के तहत उनके गंभीर रूप लेने से पहले दुरुपयोग, प्रतिगमन या कॉन्फ़िगरेशन समस्याओं का पता लगाने के लिए आवश्यकता होती है।
लंबी मतदान प्रक्रिया में त्रुटि प्रबंधन और लचीलापन
क्योंकि लॉन्ग पोलिंग कई लंबे समय तक चलने वाले कनेक्शनों पर निर्भर करती है, इसलिए क्रमिक विफलताओं या अटके हुए क्लाइंट से बचने के लिए मजबूत त्रुटि प्रबंधन महत्वपूर्ण है। सबसे पहले, प्रत्येक अनुरोध के लिए एक यथार्थवादी सर्वर-साइड टाइमआउट सेट करें ताकि किसी घटना के छूट जाने से कनेक्शन हमेशा के लिए अटके न रह जाएं।
जब नए डेटा के बिना वह समयसीमा समाप्त हो जाती है, तो सर्वर को एक स्पष्ट, सुव्यवस्थित पेलोड के साथ प्रतिक्रिया देनी चाहिए। यह एक खाली सूची हो सकती है, एक विशिष्ट JSON संरचना हो सकती है या HTTP 204 स्थिति हो सकती है, लेकिन यह पूर्वानुमान योग्य होनी चाहिए ताकि क्लाइंट "अभी तक कोई डेटा नहीं" को वास्तविक त्रुटियों से अलग कर सके।
सर्वर-साइड की वास्तविक समस्याओं – जैसे डेटाबेस में रुकावट, आंतरिक अपवाद, अमान्य पैरामीटर – के लिए सटीक HTTP स्टेटस कोड भेजना महत्वपूर्ण है। 500 (सर्वर त्रुटि), 404 (संसाधन नहीं मिला) या 401/403 (प्रमाणीकरण समस्याएँ) जैसे कोड क्लाइंट को अंधाधुंध पुनः प्रयास करने के बजाय उचित प्रतिक्रिया देने की अनुमति देते हैं।
क्लाइंट साइड पर, लॉन्ग पोलिंग के लिए एक्सपोनेंशियल बैकऑफ के साथ स्वचालित रिट्राई लॉजिक लगभग अनिवार्य है। यदि कोई अनुरोध अप्रत्याशित तरीके से विफल हो जाता है या समय समाप्त हो जाता है, तो क्लाइंट को अगला अनुरोध भेजने से पहले थोड़ा इंतजार करना चाहिए, और बार-बार विफलता होने पर प्रतीक्षा अवधि को बढ़ाना चाहिए ताकि पहले से ही दबाव में चल रहे बैकएंड पर अत्यधिक दबाव न पड़े।
स्वास्थ्य जांच और कनेक्शन स्थिति प्रबंधन भी एक अच्छे डिजाइन का हिस्सा हैं। यदि क्लाइंट को नेटवर्क लॉस या बार-बार सर्वर त्रुटियां दिखाई देती हैं, तो यह शॉर्ट पोलिंग जैसे सरल फॉलबैक तंत्र पर स्विच कर सकता है या उपयोगकर्ता को एक अनुकूल संदेश प्रदर्शित करते हुए रीयल-टाइम सुविधाओं को अक्षम कर सकता है।
अंत में, इस सभी व्यवहार को देखा जा सकना चाहिए: त्रुटियों, टाइमआउट और पुनः प्रयास पैटर्न को लॉग करें, फिर उन लॉग और मेट्रिक्स का उपयोग टाइमआउट, बैकऑफ़ रणनीतियों और बुनियादी ढांचे की क्षमता को समायोजित करने के लिए करें। लंबे समय तक चलने वाली पोलिंग प्रक्रिया का चुपचाप विफल हो जाना, नाराज उपयोगकर्ताओं और अनजाने प्रदर्शन संबंधी समस्याओं को जन्म देने का सबसे तेज़ तरीका है।
स्केलेबिलिटी, प्रदर्शन और अनुकूलन रणनीतियाँ
सामान्य तौर पर, PHP की सरल लॉन्ग पोलिंग प्रणाली बड़े पैमाने पर काम नहीं करती है, लेकिन इसे पूरी तरह से छोड़ने से पहले आप इसमें कई बदलाव कर सकते हैं। इसका लक्ष्य प्रति कनेक्शन लागत को कम करना और अपने बुनियादी ढांचे का बेहतर उपयोग करना है।
सबसे उपयोगी युक्तियों में से एक यह है कि प्रत्येक HTTP प्रतिक्रिया के लिए एक संदेश भेजने के बजाय प्रतिक्रियाओं को बैच में भेजा जाए। यदि एक ही लंबी पोल विंडो के दौरान कई इवेंट आते हैं, तो उन्हें एक ही पेलोड में एकत्रित करें ताकि आप HTTP ओवरहेड को कम कर सकें और पुनः कनेक्शन की संख्या घटा सकें।
संपीड़न से भी काफी फर्क पड़ सकता है, खासकर विस्तृत JSON पेलोड के लिए। वेब सर्वर या PHP स्तर पर Gzip (या इसी तरह के) को सक्षम करने से प्रतिक्रिया का आकार छोटा हो जाता है, डिलीवरी की गति बढ़ जाती है और बैंडविड्थ की खपत कम हो जाती है, जो बड़े पैमाने पर स्पष्ट रूप से दिखाई देती है।
कैशिंग को नजरअंदाज नहीं किया जाना चाहिए: एक समर्पित कैश लेयर बहुत सारे दोहराए जाने वाले कार्यों को अवशोषित कर सकती है जो अन्यथा आपके डेटाबेस या माइक्रोसेवाओं पर बोझ डालते। यदि कई उपयोगकर्ता समान स्ट्रीम की सदस्यता लेते हैं, तो कैश्ड स्नैपशॉट या परिकलित एग्रीगेट प्रति अनुरोध प्रसंस्करण समय को नाटकीय रूप से कम कर सकते हैं।
कनेक्शन के मामले में, पूलिंग और पुन: उपयोग मुख्य रूप से डेटाबेस या बाहरी एपीआई जैसी बैकएंड निर्भरताओं के लिए मायने रखते हैं। प्रत्येक बार पुनः कनेक्ट करने के बजाय डेटाबेस कनेक्शन को खुला रखना और उनका पुन: उपयोग करना, विशेष रूप से भारी समवर्तीता की स्थिति में, विलंबता और सीपीयू लोड को कम कर सकता है।
रेट लिमिटिंग और थ्रॉटलिंग दो भूमिकाएँ निभाते हैं: वे आपके इंफ्रास्ट्रक्चर को दुरुपयोग से बचाते हैं और लोड के तहत प्रदर्शन को पूर्वानुमानित रखने में मदद करते हैं। किसी दिए गए उपयोगकर्ता या आईपी द्वारा लंबी पोलिंग कनेक्शन खोलने की आवृत्ति को सीमित करके, आप संसाधनों की कमी के जोखिम को कम करते हैं और उचित उपयोग के लिए जगह बनाते हैं।
कई एप्लिकेशन सर्वरों में लोड बैलेंसिंग एक और शक्तिशाली साधन है। विभिन्न नोड्स में लॉन्ग पोलिंग अनुरोधों को वितरित करने से किसी एक मशीन को हॉटस्पॉट बनने से रोका जा सकता है, खासकर जब इसे स्टिकी सेशन या उपयोगकर्ता सब्सक्रिप्शन के लिए बाहरी स्टेट स्टोर के साथ जोड़ा जाता है।
अतुल्यकालिक प्रसंस्करण और पृष्ठभूमि कार्यकर्ता उन सभी चीजों को संभालेंगे जो सख्ती से "इवेंट की प्रतीक्षा करें, इवेंट भेजें" लूप का हिस्सा नहीं हैं। मैसेज क्यू, जॉब वर्कर और डिस्ट्रीब्यूटेड सिस्टम आपके लॉन्ग पोलिंग एंडपॉइंट को पतला और रिस्पॉन्सिव बनाए रखने की अनुमति देते हैं, जबकि अन्य जगहों पर भारी काम चलता रहता है।
उचित कनेक्शन और स्क्रिप्ट टाइमआउट अंतिम सुरक्षा उपाय हैं। उचित समय के बाद निष्क्रिय या अटके हुए कनेक्शनों को बंद कर दें, उन्हें सुरक्षित रखें। max_execution_time अपनी लंबी मतदान प्रक्रिया के तर्क के अनुरूप, सर्वर और क्लाइंट दोनों को कितनी देर तक प्रतीक्षा करने की अनुमति है, इस बारे में स्पष्ट रूप से बताएं।
लॉन्ग पोलिंग के लिए PHP-विशिष्ट कार्यान्वयन युक्तियाँ
साधारण PHP में लॉन्ग पोलिंग को लागू करते समय, कुछ कॉन्फ़िगरेशन और कोडिंग विवरण व्यवहार और स्थिरता में बहुत बड़ा अंतर ला सकते हैं। एक बड़ा नाम फोन कर रहा है session_write_close() स्क्रिप्ट में जितनी जल्दी हो सके।
PHP का डिफ़ॉल्ट सेशन हैंडलर फ़ाइल लॉक का उपयोग करता है, जिसका अर्थ है कि सेशन को खुला रखने वाला अनुरोध उसी उपयोगकर्ता के अन्य अनुरोधों को अवरुद्ध कर सकता है। लॉक करने वाले रिलीज़ लिखने के लिए सत्र को बंद करना, जबकि सत्र डेटा तक पढ़ने की पहुंच की अनुमति देना, ताकि अतिरिक्त समानांतर अनुरोध लंबी पोल के पीछे कतार में न लगें।
आपको आमतौर पर इसे बढ़ाना या ओवरराइड करना भी आवश्यक होगा। max_execution_time स्क्रिप्ट को 60, 120 या 300 सेकंड तक चलाने की अनुमति देने के लिए सीमा निर्धारित करें। उस बदलाव के बिना, PHP आपके लंबे पोलिंग लूप के समाप्त होने से पहले ही स्क्रिप्ट को बंद कर सकता है, जिससे क्लाइंट-साइड पर भ्रामक त्रुटियां या अधूरी प्रतिक्रियाएं हो सकती हैं।
लूप के अंदर, डेटाबेस या अन्य बैकएंड को कितनी बार एक्सेस करते हैं, इस बारे में बहुत सावधान रहें। एक तंग लूप जो हर 100 मिलीसेकंड में डेटाबेस से क्वेरी करता है, मध्यम लोड के तहत भी आपके डेटाबेस को क्रैश कर देगा; सिस्टम को प्रतिक्रियाशील बनाए रखने के लिए समझदारी से स्लीप, कैश या पुश-स्टाइल ट्रिगर का उपयोग करें।
इस लूप के भीतर लॉगिंग और मेट्रिक्स के बारे में सोचना भी महत्वपूर्ण है। टाइमआउट के कारण आप कितनी बार बाहर निकलते हैं, इसकी तुलना वास्तविक डेटा से करें, औसत प्रतीक्षा समय कितना है और आप एक साथ कितने लंबे पोल को संभालते हैं, इन सभी बातों का रिकॉर्ड रखें और फिर इन आंकड़ों को क्षमता नियोजन और कोड ट्यूनिंग में शामिल करें।
सबसे महत्वपूर्ण बात यह है कि ध्यान रखें कि प्रत्येक ब्लॉकिंग PHP स्क्रिप्ट एक वर्कर से जुड़ी होती है, इसलिए यदि आप मुट्ठी भर से अधिक उपयोगकर्ताओं को सपोर्ट करना चाहते हैं तो लूप, स्लीप और अनावश्यक काम को कम करना आवश्यक है। आंतरिक उपकरणों या कम ट्रैफ़िक वाले ऐप्स के लिए यह बिल्कुल ठीक हो सकता है; लेकिन इससे बड़े किसी भी काम के लिए, आपको अधिक मजबूत आर्किटेक्चर की आवश्यकता होगी।
वास्तविक दुनिया के पैटर्न, लाइब्रेरी और विकल्प
कई डेवलपर छोटे-छोटे डेमो के माध्यम से लॉन्ग पोलिंग के बारे में जानते हैं: एक PHP स्क्रिप्ट एक टेक्स्ट फ़ाइल पर नज़र रखती है, और जब आप उस फ़ाइल को संपादित करते हैं, तो परिवर्तन तुरंत ब्राउज़र में दिखाई देता है। यह एक बेहतरीन मानसिक मॉडल है: सरल कोड, स्पष्ट व्यवहार और त्वरित प्रतिक्रिया।
उत्पादन परिवेश में, वह तुच्छ उदाहरण शीघ्र ही उन सीमाओं तक पहुँच जाता है जिनकी हमने चर्चा की है, लेकिन फिर भी यह बुनियादी प्रोटोकॉल को दर्शाता है। एक जावास्क्रिप्ट क्लाइंट एक AJAX अनुरोध भेजता है, PHP स्क्रिप्ट तब तक अवरुद्ध रहती है जब तक कि फ़ाइल में परिवर्तन नहीं होता या टाइमआउट नहीं हो जाता, फिर प्रतिक्रिया देती है और प्रक्रिया दोहराती है।
विशेष रूप से PHP इकोसिस्टम के लिए, आपको कुछ ऐसे फ्रेमवर्क और पैटर्न मिलेंगे जो इसे अधिक प्रबंधनीय बनाने का प्रयास करते हैं। उदाहरण के लिए, Laravel डेवलपर्स को WebSockets या प्रबंधित सेवाओं के माध्यम से इवेंट प्रसारित करने के लिए प्रेरित करता है, हालांकि आप मैन्युअल रूप से लॉन्ग पोलिंग रूट भी सेट कर सकते हैं।
पीएचपी के अलावा, लगभग हर भाषा में परिपक्व फ्रेमवर्क मौजूद हैं जो या तो सीधे लॉन्ग पोलिंग का समर्थन करते हैं या रीयल-टाइम संचार के आसपास बेहतर अमूर्तता प्रदान करते हैं। Node.js के साथ Express.js या Socket.IO, Python के साथ Flask या Django Channels, Java के साथ Spring, Ruby on Rails, और .NET के साथ ASP.NET SignalR सभी लोकप्रिय विकल्प हैं।
कुछ प्लेटफॉर्म स्केलिंग और कनेक्शन की पूरी समस्या को आपसे पूरी तरह से छिपा देते हैं। प्रबंधित रीयल-टाइम सेवाएं - जिनमें पब/सब मैसेजिंग और उपस्थिति पर केंद्रित सेवाएं शामिल हैं - क्लाइंट एसडीके, एन्क्रिप्शन, बारीक एक्सेस कंट्रोल और लाखों समवर्ती कनेक्शनों को संभालने के लिए वैश्विक बुनियादी ढांचा प्रदान करती हैं, इसलिए आपको नए सिरे से सब कुछ बनाने की आवश्यकता नहीं है।
PHP की दुनिया में, आप अक्सर अपने मौजूदा एप्लिकेशन लॉजिक को इस तरह की रीयल-टाइम सेवा के साथ मिलाकर दोनों दुनियाओं का सर्वश्रेष्ठ लाभ प्राप्त कर सकते हैं। PHP व्यावसायिक नियमों, डेटा की निरंतरता और API के लिए जिम्मेदार रहता है, जबकि बाहरी प्लेटफ़ॉर्म उपयुक्त रूप से लॉन्ग पोलिंग, SSE या WebSockets के माध्यम से लंबे समय तक चलने वाले कनेक्शन, फैन-आउट और रीयल-टाइम डिलीवरी को संभालता है।
अन्य इकोसिस्टम इन रीयल-टाइम रणनीतियों को कॉमेट, रिवर्स एजेक्स, एचटीपी स्ट्रीमिंग, पुशलेट या एजेक्स लॉन्ग पोलिंग जैसे नामों से लेबल करते हैं। असल में, ये सभी एक ही विचार के अलग-अलग रूप हैं: मूल रूप से अनुरोध/प्रतिक्रिया प्रोटोकॉल को कुछ ऐसा बनाना जो पुश-आधारित जैसा महसूस हो।
PHP डेवलपर्स जो लॉन्ग पोलिंग की समस्याओं से जूझ रहे हैं, उनके लिए महत्वपूर्ण यह है कि वे अपनी समवर्ती आवश्यकताओं, अपने होस्टिंग वातावरण और आप कितनी जटिलता को स्वीकार करने के लिए तैयार हैं, इसका ईमानदारी से आकलन करें। कभी-कभी एक साधारण ब्लॉकिंग लूप ही काफी होता है; अन्य समयों में इवेंट लूप लाइब्रेरी को अपनाना, पुश को एक समर्पित सेवा में स्थानांतरित करना या अपने स्टैक के कुछ हिस्से को बड़ी संख्या में खुले कनेक्शनों के लिए निर्मित तकनीक में बदलना बेहतर होता है।
जब आप इन सभी पहलुओं को एक साथ रखते हैं - HTTP की कार्यप्रणाली, PHP का निष्पादन मॉडल, सर्वर आर्किटेक्चर, सुरक्षा, त्रुटि प्रबंधन और स्केलेबल डिज़ाइन पैटर्न - तो लॉन्ग पोलिंग एक रहस्यमय प्रदर्शन को बाधित करने वाला कारक नहीं रह जाता है, बल्कि एक और उपकरण बन जाता है जिसका उपयोग आप सोच-समझकर वहीं कर सकते हैं जहाँ यह समझ में आता है।