ब्लॉग

एक जड चॅट आमचा API कसा खाली पाडू शकत होता

28 सप्टेंबरला, एका release नंतर सुमारे 17 मिनिटांनी, आमचे दोन्ही production API सर्व्हर एकाच क्षणी मेमरीबाहेर गेले, restart झाले, आणि सुमारे पाच मिनिटे load balancer कडे पाठवण्यासाठी एकही निरोगी सर्व्हर नव्हता. आमच्या पहिल्या दुरुस्तीने API ला दुप्पट मेमरी दिली. खरे कारण त्याच दिवशी नंतर सापडले: एक विशिष्ट चॅट उघडल्यावर API ने एका request मध्ये 53 MB संदेश लोड करण्यास सांगितले होते. चॅट इतिहास आता पृष्ठांनी लोड होतो, संख्येबरोबरच आकारानेही मर्यादित, आणि ती चॅट क्रॅश होण्याऐवजी 5 MB च्या पहिल्या पानासह उघडते.

काय बंद पडले

आमचा API प्रत्येक दोन सर्व्हरवर एका container म्हणून चालतो, load balancer मागे. प्रत्येक container ची मेमरी मर्यादा 384 MiB होती. विश्रांतीच्या वेळी तो 130–140 MiB वापरतो, त्यामुळे मर्यादा भरपूर मोकळी वाटत होती.

दोन्ही containers एकाच वेळी ती मर्यादा गाठले आणि “JavaScript heap out of memory” ने क्रॅश झाले. Heap म्हणजे Node.js प्रक्रिया ज्या objects सोबत काम करते त्यासाठीची मेमरी. दोन्ही सर्व्हर एकाच वेळी अपयशी झाल्यामुळे request पाठवण्यासाठी कुठेही जागा उरली नाही. दोन सर्व्हरच्या सेटअपसाठी हा सर्वात वाईट प्रकारचा outage आहे: एक सर्व्हर मेला तरच redundancy उपयोगी पडते, अपयश एकाच वेळी आले तर नाही.

पहिली दुरुस्ती: अधिक जागा

वेळ release कडे निर्देश करत होती. Release नंतर, deploy ने व्यत्यय आणलेले agent turns पुन्हा सुरू होतात आणि त्यांचे transcripts पुन्हा जतन करतात, आणि तो अतिरिक्त कामाचा स्फोट मेमरी वाढीचे स्पष्ट कारण वाटत होता.

त्यामुळे पहिल्या बदलात API ची मर्यादा 384 MiB वरून 768 MiB केली. ती आम्ही त्याच दिवशी दोन्ही सर्व्हरवर थेट लागू केली, आणि पुढच्या deploy मध्ये 384 चुपचाप परत येऊ नये म्हणून deploy configuration मध्ये कमिट केली. हाताने सर्व्हरवर केलेली दुरुस्ती जी पुढचा deploy उलटवतो, तोच outage पुन्हा येण्याचा सामान्य मार्ग आहे.

अधिक मेमरी ही वाजवी सुरक्षितता राखीव होती. ती स्पष्टीकरण नव्हती.

खरे कारण: एक request, 71 MB

नंतर त्याच दिवशी आम्ही एका चॅटच्या प्रतीवर क्रॅश पुनरुत्पादित केला, production ची जुनी मेमरी मर्यादा वापरून. ती प्रत API ला स्वतःहून क्रॅश करत होती, कोणताही deploy न होता.

प्रोजेक्ट उघडल्यावर वेब अ‍ॅप चॅटचा इतिहास API कडे मागतो. Endpoint शेवटचे 30 संदेश पूर्ण परत करत होता. बहुतेक चॅट्ससाठी 30 संदेश लहान असतात. या चॅटसाठी शेवटच्या 30 संदेशांचा आकार database मध्ये 53 MB आणि response 71 MB होता. एजंटची काही उत्तरे प्रत्येकी 4–10 MB होती, मुख्यत्वे sub-agents चे transcripts: मुख्य एजंट कामाचा एक भाग समांतर करण्यासाठी सुरू करत असलेले मदतनीस एजंट, ज्यांचे संपूर्ण काम उत्तराबरोबर जतन होते.

ती एक response बांधण्यासाठी API कडे असलेल्या heap पेक्षा जास्त जागा लागत होती. आणि त्या प्रोजेक्टवर प्रत्येक उघडणे किंवा refresh केल्यावर request पुन्हा जात होती. एकच चॅट त्या कोणत्याही सर्व्हरला खाली पाडू शकत होती जिथे ती पोहोचत होती, आणि पेज reload करता येत असल्यामुळे ती दोन्हीपर्यंत पोहोचू शकत होती.

“30 संदेश” ही कधीच खरी आकार मर्यादा नव्हती. ती संख्येवरील मर्यादा होती, जी सामान्य चॅट्ससाठी योगायोगाने लहान होती.

उपाय: आकार आणि संख्या दोन्हीने मर्यादित पाने

इतिहासाचे एक पान आता 30 संदेश किंवा सुमारे 4 MB, जे आधी येईल ते.

ते दोन पायऱ्यांत चालते:

  1. आधी आकार विचारा. API database कडे सर्वात नव्या संदेशांचे IDs आणि साठवलेले आकार मागतो, त्यांची सामग्री न घेता. ती query संदेश कितीही मोठे असले तरी स्वस्त असते.
  2. जे बसते तेवढेच लोड करा. सर्वात नव्यापासून सर्वात जुन्यापर्यंत चालत, पुढचा संदेश पानाला 4 MB च्या पलीकडे ढकलेल तोपर्यंत संदेश जोडतो. त्या ओळीच नंतर पूर्णपणे लोड होतात.

दोन नियम हे सुरक्षित ठेवतात:

  • सर्वात नवा संदेश आकार काहीही असला तरी पानावर जातो. काहीही परत न देणारे पान चॅट अडकवेल, मागे स्क्रोल करण्याचा मार्ग उरणार नाही.
  • काहीही कापले जात नाही. कोणताही संदेश छाटला किंवा वगळला जात नाही. चॅटचा उरलेला भाग “जुने संदेश पाहण्यासाठी वर स्क्रोल करा” नियंत्रणाद्वारे लोड होतो, जुने संदेश आधीपासून वापरत असलेले, एका वेळी एक पान.

आणखी एका ठिकाणी तोच आकार सापडला. तुम्ही एखादा turn थांबवता तेव्हा API शेवटच्या काही उत्तरांकडे पाहतो की कोणते रिकामे आहे आणि साफ करायला हवे. तो आठ पूर्ण संदेश लोड करून हे करत होता. मल्टि-मेगाबाइट उत्तरांच्या चॅटवर हीच समस्या लहान स्वरूपात होती. आता तो database ला एक हो-किंवा-नाही प्रश्न विचारतो — या संदेशात काही सामग्री आहे का? — सामग्री स्वतः लोड न करता.

आम्ही ते कसे तपासले

चॅटच्या प्रतीवर, जुन्या 384 MiB मर्यादेखाली चालवताना:

  • पहिले पान 5 MB आहे. आधी तीच request API ला क्रॅश करत होती.
  • एकाच वेळी पाच ब्राउझर tabs मध्ये चॅट उघडल्यावर मेमरी 154 MB वर पोहोचते.
  • संपूर्ण चॅटमध्ये मागे स्क्रोल केल्यावर सर्व 190 संदेश परत येतात, प्रत्येक एकदा, क्रमाने.

पान-निवडीच्या logic साठी unit tests आहेत, त्यात एक चाचणी त्या चॅटच्या सर्वात नव्या संदेशांच्या खऱ्या आकारांवरून बांधलेली आहे. पहिल्या पानावर एक संदेश येतो, अजून आहेत असे सांगितले जाते, आणि पुढचे पान त्यानंतरच्या संदेशापासून सुरू होते.

आम्ही काय शिकलो

  • संख्या ही आकार मर्यादा नाही. “सर्वात नवे N” परत देणारा कोणताही endpoint, जो अमर्यादपणे वाढू शकतो, त्याला byte budget हवे. डेटा शेवटी ती पोकळी शोधतोच.
  • उघड संशयित नेहमी कारण नसतो. Deploy हे अतिरिक्त कामाचे खरे ट्रिगर होते, आणि अधिक मेमरी मोलाची होती. पण क्रॅश deploy शिवाय पुनरुत्पादित झाला, आणि ते पुनरुत्पादित न करता आम्ही मेमरी वाढीवर थांबलो असतो.
  • दोन सर्व्हर एकाच request मुळे एकत्र अपयशी होतात. Redundancy एका सर्व्हरच्या मृत्यूपासून संरक्षण देते. ती ज्या request ने कोणताही सर्व्हर गाठला तो मारतो त्यापासून संरक्षण देत नाही, विशेषतः ज्याला वापरकर्ता पेज refresh करून सहज पुन्हा करेल.
  • ती config मध्ये दुरुस्त करा, फक्त बॉक्सवर नाही. मेमरी वाढ त्याच दिवशी deploy configuration मध्ये गेली, त्यामुळे पुढचा deploy ती राखतो.

ही अलीकडची दुसरी मेमरी कथा आहे ज्यात एजंटचे आउटपुट होते. पहिली म्हणजे progress label ने 690 MB strings रांगेत टाकल्याची घटना. Mythex वर sub-agents वापरत असाल तर ते कसे काम करतात ते docs मध्ये वाचा.

Mythex · Pricing · AI सह काहीही बनवा · वेबसाइट आणि अ‍ॅप टेम्प्लेट्स · Mythex ची तुलना · AI अ‍ॅप निर्मिती शब्दावली · मोफत AI अ‍ॅप निर्मिती साधने · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)