- CGI प्रोग्रामिंग से भी एक दिन में 20 करोड़ से अधिक वेब अनुरोध संभालना संभव है
- हाल के हार्डवेयर प्रदर्शन सुधारों से CGI तरीके की कमियां काफी घट गई हैं
- Go और SQLite का उपयोग करने वाला CGI प्रोग्राम 16-thread CPU पर शानदार प्रदर्शन दिखाता है
- CGI, कई CPU core के उपयोग के लिए विशेष रूप से उपयुक्त संरचना प्रदान करता है
- आधुनिक तकनीक की वजह से वेब एप्लिकेशन डेवलपमेंट के पुराने तरीके भी पूरी तरह व्यावहारिक हो सकते हैं
CGI का अतीत और वर्तमान
- 1990 के दशक के उत्तरार्ध में, लेखक ने CGI से वेब डेवलपमेंट शुरू किया था और उस समय NewsPro जैसे सिस्टम इस्तेमाल किए जाते थे
- CGI में हर वेब अनुरोध पर नया process शुरू और बंद होता है, जिससे ऊंचा overhead पैदा होता है
- इसी कारण अधिक कुशल PHP, FastCGI जैसी वैकल्पिक तकनीकें विकसित हुईं
हार्डवेयर प्रदर्शन का विकास
- पिछले 20 से अधिक वर्षों में कंप्यूटर की गति और प्रदर्शन तेज़ी से बढ़े हैं
- 2020 में लेखक ने Go और Rust से बने टूल्स (
ripgrep आदि) का उपयोग करते हुए process-execution तरीके की व्यावहारिकता को फिर से पहचाना
आधुनिक CGI तरीके के फायदे
- Go और Rust जैसी तेज़ execution वाली भाषाओं में CGI लागू करने पर पुराने CGI की ज्यादातर कमियां दूर हो जाती हैं
- CGI प्रोग्राम प्रत्येक अनुरोध के लिए अलग process में चलते हैं, इसलिए multi-core CPU के उपयोग के लिए अनुकूलित होते हैं
- उदाहरण के लिए, 16-thread वातावरण में 2400 से अधिक अनुरोध/सेकंड = 20 करोड़+ अनुरोध/दिन संभालने की संभावना की पुष्टि हुई
- बड़े सर्वर 384 से अधिक CPU thread उपलब्ध करा सकते हैं
डेवलपमेंट संस्कृति पर अंतर्दृष्टि
- आज Go, Rust जैसी भाषाओं के आने से 1990 के दशक की CGI पद्धति फिर से अर्थपूर्ण हो सकती है
- हालांकि, यह अब भी हर वातावरण के लिए उपयुक्त तरीका नहीं है और इसे मुख्यधारा के तरीके के रूप में अनुशंसित नहीं किया जाता
- महत्वपूर्ण बात यह है कि अब CGI पहले की तरह अकुशल समाधान नहीं है, यह बात प्रयोगात्मक रूप से साबित हुई है
निष्कर्ष
- आधुनिक हार्डवेयर और तेज़ भाषाओं के समर्थन के साथ CGI प्रोग्रामिंग, अतीत की तुलना में कहीं बेहतर प्रदर्शन दिखाती है
- यह multi-process के फायदों का अधिकतम उपयोग करने वाला एक उदाहरण है और वेब डेवलपर्स के लिए दिलचस्प संकेत देता है
1 टिप्पणियां
Hacker News टिप्पणियाँ
आजकल Python में भी CGI काफ़ी तेज़ महसूस होता है
अगर CGI स्क्रिप्ट शुरू होते समय CPU पर 400 मिलीसेकंड भी ले, तब भी अगर सर्वर में 64 कोर हों तो प्रति सेकंड 160 रिक्वेस्ट संभाले जा सकते हैं, यानी एक दिन में प्रति सर्वर 1.4 करोड़ ट्रैफ़िक प्रोसेस हो सकता है
इसका मतलब, रोज़ाना सैकड़ों मिलियन ट्रैफ़िक स्तर पर भी (static assets को छोड़कर) CGI process startup bottleneck नहीं है
पहले लगता था कि यह ऐसी "उबाऊ हद तक स्थिर तकनीक" है जो हमेशा Python standard library में रहेगी, लेकिन आजकल Python maintainers का रुख़ उल्टा stability और backward compatibility के ख़िलाफ़ दिखता है
इसलिए बहुत ज़्यादा 'उबाऊ और स्थिर' modules को standard library से हटाया जा रहा है, और वास्तव में
cgimodule को 3.13 version में हटा दिया गयालगभग 25 साल से Python को prototyping के लिए इस्तेमाल करने की आदत रही है, लेकिन अब पछतावा होने लगा है
JS और Lua के बीच झूलने जैसा मन है
cgiहटाने पर आधिकारिक स्पष्टीकरण का लिंक है PEP 594 cgiइस लिंक से 2000 में (25 साल पहले) लिखे गए PEP 206 तक पहुँचा जा सकता है, जहाँ तब भी लिखा था कि "
cgipackage की design ठीक नहीं है और इसे छूना भी मुश्किल है"jackrosenthal/legacy-cgi repository में standard library module का वैसा ही drop-in replacement देखा जा सकता है
Python developers ने सिर्फ
cgiनाम वाला module हटाया हैCGI script implementation अभी भी
http.servermodule केCGIHTTPRequestHandlerमें supported हैयह भी याद दिलाया गया कि मूल
cgimodule में HTML form data parse करने वाले कुछ functions ही थेPython में
cgimodule के standard library से हटने की आलोचना समझ में आती है, लेकिन जिसकी अक्सर मिसाल दी जाती है, वह JS तो वैसे भी standard library नहीं हैLua में भी stdlib में CGI module नहीं है, यह बात भी उठाई गई
व्यक्तिगत रूप से PHP या JS पसंद है
ऐसे मामलों में box से बाहर ही JIT मिल जाना सुविधाजनक है
Python 1.6 से इस्तेमाल कर रहा हूँ, लेकिन ज़्यादातर OS scripting के लिए
पहले Tcl को Apache या IIS module के रूप में जोड़कर बार-बार modules को C में फिर से लिखने का अनुभव रहा है (1999~2003)
अगर CGI script 400 मिलीसेकंड CPU इस्तेमाल करती है, तो उस endpoint का response time भी कम से कम उतना ही हो जाएगा, जिससे usability पर असर पड़ेगा
हाल में 350 डॉलर के mini server पर golang binary, rabbitmq, redis, MySQL चलाकर उसी सर्वर पर लगातार 5,000 req/s संभाले
24 घंटे में यह 40 करोड़ requests की क्षमता है
आजकल के free tools वाकई शानदार हैं, यह महसूस हुआ
फिर भी cloud cost बहुत ज़्यादा लगती है
बेशक 1:1 तुलना मुश्किल है, लेकिन development और tuning को घर के basement server पर खुद कर पाने की संतुष्टि बड़ी थी
Kubernetes-आधारित microservices के ढेर के साथ development speed 10 गुना धीमी हो जाने वाले मामले भी हैं
बहुत लोग यह नहीं समझते कि server ऐसी मशीन नहीं है जो सिर्फ़ 1 request per second ही संभालती हो
सिर्फ़ इसलिए कि Google ऐसा करता है, उसी के पीछे चलकर लोग बहुत ज़्यादा overhead चुका रहे हैं
मुझे भी लगा कि हमारी टीम पर अच्छे से फिट होने वाली 'modular monolithic' architecture पर लिखना चाहिए
side project को घर से self-host करने की कोशिश की, लेकिन power outage, ISP downtime, remote access failure, hard drive crash जैसी risks बहुत हैं
आख़िरकार अपना समय जोड़ें तो आर्थिक फ़ायदा भी साफ़ नहीं रहता
cloud services economies of scale का लाभ लेती हैं, इसलिए वास्तव में यह एक तर्कसंगत विकल्प है
ज़रूरी नहीं कि cloud ही हो, hosting provider से dedicated server किराए पर भी लिया जा सकता है
हाँ, bandwidth/traffic limits होती हैं
cloud के mainstream होने की वजह VC और investors का उनमें stake होना, या यह डर भी है कि "कहीं अनंत ट्रैफ़िक न फूट पड़े"
cloud sales वाले निवेशकों की इस चिंता को बड़ी चालाकी से भुनाते हैं
ज़रूरी नहीं कि हर कोई cloud ही इस्तेमाल कर रहा हो
असली services में VM cost ज़्यादा होने की वजह high-performance compute नहीं, बल्कि बहुत बड़े local disk capacity की ज़रूरत होती है
बहुत ऊँची compute power की ज़रूरत नहीं, 20TB की 4 drives और एक ठीक-ठाक CPU से भी शानदार service की कल्पना की जा सकती है
cloud में ऐसा combination मिलना लगभग असंभव है
cgi-binमें अगर DB access चाहिए, तो हर बार process को DB connection नया बनाना पड़ता है, यह असुविधाजनक हैअगर code memory में चल रहा हो (जैसे fastcgi), तो सिर्फ़ startup time कम नहीं होता, बल्कि DB connection pool या per-thread persistent connection भी बनाए रखे जा सकते हैं
बड़े scale पर DB connections बहुत ज़्यादा हो जाते हैं और DB पर दबाव बढ़ता है
"Python single-threaded है, इसलिए कई processes चाहिए; Python धीमा है, इसलिए और ज़्यादा processes चाहिए" जैसी वजहों से बहुत से processes चलाए जाते हैं
आख़िर में Python process के बाहर shared connection pool (
pg bouncerवगैरह) अलग रखना पड़ता है, और तरह-तरह की tuning चाहिएअंत में इसे किसी ज़्यादा संभालने योग्य भाषा में (जिसमें multithreading support हो और performance बेहतर हो) फिर से implement किया, और चीज़ें काफ़ी सरल हो गईं
इसलिए आख़िरकार CGI ऐसे मॉडल की तरफ़ बढ़ा जिसमें requests के बीच state/info बची रहे (जैसे fastcgi)
पारंपरिक तौर पर अलग daemon चलाकर उसे proxy की तरह इस्तेमाल किया जाता था, और Unix socket का उपयोग TCP/IP से कहीं ज़्यादा efficient था
UDP इस्तेमाल करने की राय
मेरे लिए
inetdही असल CGI हैउसी की वजह से इंटरनेट बहुत ज़्यादा मज़ेदार लगा
वह दौर जब
inetdसे कई shell scripts, यहाँ तक कि सिर्फ़ Bash में लिखा HTTP भी चलता थापुराने VPS, backups या version control के बिना पड़े laptops अब खो गए, लेकिन वे मज़ेदार यादें हैं
deployment भी
Makefile + scpसे सीधा-सादा था, और testing भीnetcatऔरgrepसे लिखी Bash scripts से हो जाती थीसच में, जीने के लिए बढ़िया ज़माना है
hello worldapp का 2400 rps (प्रति सेकंड request throughput) हासिल करना आज के hardware के हिसाब से कुछ ख़ास नहीं लगताcode भी ज़्यादा सरल नहीं हुआ, तो फिर समझ नहीं आता कि किसलिए performance की क़ुर्बानी दी जा रही है
अगर 2000 rps से ज़्यादा संभालने की ज़रूरत नहीं है, तो इसमें कोई समस्या नहीं
ऐसा ट्रैफ़िक चाहिए भी बहुत कम sites को, यही तर्क है
numbers के हिसाब से बहुत ऊँचा नहीं है, लेकिन व्यवहार में कई environments के लिए काफ़ी है
HN developers जिस 'hug of death' (किसी एक पल में ट्रैफ़िक का अचानक उछाल) की बात करते हैं, उसे भी यह झेल सकता है
हमारी company में अभी भी simple internal webapps को जल्दी खड़ा करने के लिए
cgi-bindirectory वाला तरीका इस्तेमाल होता हैसरल इस्तेमाल में development efficiency बहुत अच्छी मिलती है
CGI होने पर भी
http/1.0को सीधे print करने की ज़रूरत नहीं, और Python केwsgiref.handlers.CGIHandlerका इस्तेमाल करके किसी भी WSGI app को CGI script की तरह चलाया जा सकता हैFlask example code भी नीचे की तरह सरल है
production में
uwsgiके CGI plugin से scripts चलाते हैंApache या lighttpd में
mod_cgiचलाने से यह कहीं ज़्यादा सरल और flexible लगता हैuwsgisystem unit के रूप में चलता है, इसलिएsystemdकी hardening और sandboxing सब इस्तेमाल की जा सकती है, यह भी फ़ायदा हैसाथ ही,
uwsgiके CGI handling में हर file type के लिए interpreter अलग से तय किया जा सकता हैfirst byte भेजने तक 250~350ms लगते हैं, और हमारे use case के लिए यह पूरी तरह स्वीकार्य है
uwsgi cgi संबंधित दस्तावेज़
wsgiref.handlers.CGIHandlerअभी deprecated नहीं हुआ है, यह जानकारी उपयोगी हैकल चर्चा हुआ संबंधित thread लिंक
हाल में side project के लिए Apache इस्तेमाल करते समय
.htaccessfeature उपयोगी लगाकिसी भी directory में सिर्फ़
.htaccessfile रख दें, तो हर individual request पर अतिरिक्त server config load हो जाती हैhtaccess आधिकारिक दस्तावेज़
पहले हर request पर disk access के overhead की वजह से performance के लिहाज़ से
.htaccessसे बचने और इसे main config में समेटने की सलाह दी जाती थीलेकिन अब SSD और RAM काफ़ी हैं, इसलिए performance में हल्का-सा नुकसान ज़रूर है, मगर CPU भी इतने अच्छे हैं कि ज़्यादातर मामलों में इसे नज़रअंदाज़ किया जा सकता है
[मेरे प्रोजेक्ट StaticPatch][https://github.com/StaticPatch/StaticPatch/tree/main] में भी इसे पहले से लागू करके इस्तेमाल कर रहा हूँ
PHP creator Rasmus Lerdorf का मशहूर कथन
"मैं कोई असली programmer नहीं हूँ, मैं बस चीज़ों को चलने लायक बना देता हूँ और आगे बढ़ जाता हूँ। असली programmers कहते हैं, 'इसमें बहुत memory leaks हैं, इसे ठीक करना चाहिए।' मैं तो बस हर 10 बार पर apache restart कर देता हूँ"
उसके बाद PHP ने लंबा सफ़र तय किया और शुरुआती ग़लतियों से उबरते हुए बहुत विकसित हुआ
यह किस्सा भी है कि उन्होंने कहा था, "PHP 8 मुझे उतना ही बेहतर लगता है जितना कम code मैं लिखूँ"
समझ नहीं आता कि Apache file system को watch करके सिर्फ़ बदलाव होने पर ही क्यों नहीं पढ़ सकता, हर request पर बेवजह disk access क्यों कराता है
नतीजा यह कि 99.99% http requests धीमी हो जाती हैं, यही आपत्ति है
हाल की workflow में तेज़ prototyping के लिए इस तरह की संरचना पर विचार कर रहा हूँ
JIT languages में fastcgi जैसा रूप न हो तो import bottleneck बन जाता है
मैंने खुद इस्तेमाल किया हुआ
h2oweb server,mrubyऔर fast-cgi handler के config files के साथ इतना सरल है कि local script काम के लिए एकदम ठीक बैठता हैh2o fastcgi दस्तावेज़
एक और फ़ायदा यह है कि जब local software को इस तरह extend करना हो कि ग्राहक खुद custom code जोड़ सकें, तब भी यह काम आता है
उदाहरण के लिए, पहले extension के लिए MCP इस्तेमाल करना पड़ता, लेकिन अब CGI में structured requests implement कर दें तो काम हो जाता है
end-user environment के रूप में इस्तेमाल करना हो तो MCP front से CGI programs को जोड़ना भी सोचने लायक idea है
MCP service भी काफ़ी हद तक CGI में implement की जा सकती है
spec को और ध्यान से देखने की ज़रूरत महसूस हो रही है
यह सवाल भी है कि fastcgi में CGI के लगभग सारे फ़ायदे ख़त्म नहीं हो जाते क्या
पहले C program और CGI का संयोजन सीधे इस्तेमाल किया है
उस समय 100 से ज़्यादा cores या भरपूर RAM नहीं थी, और ज़्यादा से ज़्यादा 1GB memory में भी काम चल जाता था
तब जो संभव था, उसे देखकर यक़ीन है कि आज यह और भी आसान होगा
load balancing की ज़रूरत पड़ने के बाद scale करना मुश्किल हुआ, लेकिन उससे पहले तक यह काफ़ी अच्छी तरह काम करता था
संदर्भ के लिए, front और back office के लिए अलग-अलग 2 executables थे