मैंने एक उपयोगकर्ता को 8 फरवरी को इस पोस्ट को लिखने का वादा किया था, और वादों को रखा जाना चाहिए।
इसने मुझे यह वादा करने के लिए प्रेरित किया, निश्चित रूप से, यह बताने की इच्छा नहीं थी कि उस दिन की शाम में हमारी
साइट पर सर्फिंग (सिफारिशें प्राप्त करने की प्रक्रिया) ने पांच सौ क्यों दिए, लेकिन अधिक सामान्य विचार।
अर्थात्, उपयोगकर्ता ने लगातार हमें शक्ति बढ़ाने की सलाह दी, अन्यथा यह पहले से ही असंभव है।
हमारे पास पर्याप्त शक्ति है। उपयोक्ता के उपद्रवी और आत्मविश्वास ... मुझे परेशान किया, और इसीलिए मैंने यह लिखने का फैसला किया कि वास्तव में साइटें अक्सर नीचे क्यों जाती हैं।
अस्वीकरण: हाँ, साइटें तुच्छ कारणों से झूठ बोल सकती हैं जैसे कि बिजली, या भौतिक सर्वर विफलता, डेटा केंद्र में समस्याएं, खराब कोड, प्रशासक त्रुटियां। मैं थोड़ा और सूक्ष्म कारणों के बारे में बात करना चाहता हूं जो प्रोग्रामर भी नहीं जानते हैं या नहीं सोच सकते हैं कि क्या उन्हें वेब प्रोजेक्ट विकसित नहीं करना था।
तो यहाँ है। हमेशा की तरह, अगर कुछ कहीं नीचे चला गया, तो कुछ कहीं गायब था।
पहले उम्मीदवारों में से एक प्रक्रिया की कमी है जो अनुरोधों को संसाधित करता है। हमारे मामले में, यह FastCGI है, लेकिन बात नहीं है।
इसके अलावा, बिंदु, सबसे अधिक संभावना है, वे बस कुछ ही नहीं हैं - तथ्य यह है कि वे अचानक अस्वीकार्य रूप से लंबे समय तक काम करना शुरू कर देते हैं, और खुद को मुक्त करने का समय नहीं है।
ऐसा क्यों हो रहा है? कुछ हद तक भरी हुई साइट एक उच्च अनुकूलित प्रणाली है। यह इस तथ्य के लिए डिज़ाइन किया गया है कि अधिकांश डेटा कैश में है, डेटाबेस क्वेरी को जल्दी से निष्पादित किया जाता है ताकि js में कोई त्रुटि आपको ddos के अनुरूप न लगे :-)
दरअसल, यह कुंजी है - जब इसका उल्लंघन किया जाता है, तो गोता तेज हो जाता है। ऐसी चीजों को परीक्षणों में पकड़ना मुश्किल हो सकता है।
उदाहरण के लिए, एक परीक्षण सर्वर पर, आप यह नहीं देख सकते हैं कि अजाक्स अनुरोध डेढ़ गुना अधिक भेजा जाना शुरू हो गया है - लोड लगभग शून्य है (आप में से पांच वहां हैं और डेटाबेस गीगाबाइट में फिट बैठता है) और सब कुछ काम करता है।
यह भी आसान नहीं है कि कोड में बदलाव के परिणामस्वरूप, अब कभी-कभी (शायद दसियों / सैकड़ों अनुरोधों के लिए एक बार) इस तरह का अनुरोध डेटाबेस में उत्पन्न होता है जो सूचकांक द्वारा कवर नहीं किया जाता है।
या आप एक नया फ़ंक्शन बनाते समय थोड़ा गलत थे, और इसका परिणाम कभी भी कैश से नहीं लिया जाता है - परीक्षण एक पर, और इसलिए यह काम करता है। या, आपने त्रुटिपूर्ण पैकेज अपडेट के बाद क्लस्टर से एक मेमेकैच किया है।
ऐसे मामलों में वास्तव में क्या होता है? जब यह डेटाबेस के बारे में नहीं है, तो सब कुछ सरल है, अधिक अनुरोध हैं / वे लंबे हो गए हैं, प्रक्रियाएं दुर्लभ हो गई हैं, फ्रंट-एंड ग्राहकों को पांच सौ बार बाहर देता है।
एक आधार और एक दुर्लभ अनुरोध के साथ - अधिक दिलचस्प। सबसे पहले, तैनाती के बाद, सब कुछ ठीक है। फिर डेटाबेस में एक भारी अनुरोध दिखाई देता है। आप शायद अभी भी कुछ भी नोटिस नहीं करेंगे। इस तरह का अनुरोध भेजने वाली प्रक्रिया लटकी हुई है। ऐसे अनुरोध तेजी से दिखाई देने लगते हैं, जैसे वे निष्पादित हो रहे हैं, और उनमें से दो, तीन, 5 हैं, और अब सर्वर कोर के आधे इन अनुरोधों में लगे हुए हैं, और डिस्क पूर्ण लोड में चली जाती है।
बधाई - सबसे अधिक संभावना है कि आप पहले से ही नीचे हैं। साधारण, आसान अनुरोधों का जवाब देने के लिए आधार बहुत लंबा हो गया है, और जैसे ही प्रक्रिया किसी कारण से वहां जाती है, यह वास्तव में लटका हुआ है। जल्दी या बाद में हर कोई वहाँ लटका रहता है।
यहां तक कि अगर आपके एप्लिकेशन ने टाइमआउट को सही ढंग से कॉन्फ़िगर किया है - और यह करने योग्य है - वैसे भी, आपकी सेवा का कुछ हिस्सा गिर गया है, और बाकी ने धीरे-धीरे काम करना शुरू कर दिया है, क्योंकि समय-समय पर चिपके रहना अच्छा नहीं है।
उनकी संख्या द्वारा प्रक्रियाओं की कमी को हराना असंभव है। सबसे पहले, नए लोग भी कुंद करेंगे, केवल एक भी बड़ी भीड़ बनाएँ; दूसरे, वे स्मृति में आराम करेंगे।
डेटाबेस की क्षमता बढ़ाने का निर्णय करना भी एक विकल्प नहीं है, एक खराब अनुरोध को बड़े संसाधनों के परिमाण के आदेश की आवश्यकता हो सकती है।
सामान्य तौर पर, केवल बौद्धिक रूप से व्यवहार करें। और इस तथ्य के लिए तैयार होने के लिए कि सिस्टम जितना अधिक अनुकूलित होगा, उतना ही नाजुक - जितना अधिक गिरने के लिए उतना ही दर्दनाक होगा, इसलिए बोलने के लिए :-)
प्रक्रियाओं की कमी के गैर-प्रतिबंधात्मक कारणों के और क्या हैं।
मेमोरी लीक - और, इसलिए, एक स्वैप के लिए छोड़कर, ठीक है, सब कुछ पहले से ही धीमा होने लगा है।
ताज पर स्क्रिप्ट के लॉन्च के दौरान वही स्वैप हो सकता है। एक कपटी लिपि को आधार की वृद्धि के साथ अधिक मेमोरी की आवश्यकता हो सकती है, शायद चतुष्कोणीय रूप से भी बढ़े - और पीड़ित मशीन इस समय के लिए बहुत बुरा महसूस करेगी। यह वास्तव में मजेदार है यदि
OOM हत्यारा आता है और उदाहरण के लिए, आपके आधार की प्रक्रिया डालता है।
खुली फाइलों (या सॉकेट्स) की संख्या में लीक - और भी सब कुछ तुरंत मर गया।
अनन्त चक्र जो शायद ही कभी होता है - यह सबसे अच्छा लगता है।
बस एक बहुत लंबा चक्र, जिसकी संभावना प्रोग्रामर द्वारा चूक गई थी और जो काउंटर पर बल द्वारा बाधित नहीं है - वहां भी।
ऑफहैंड, फंतासी समाप्त :-)
प्रक्रियाओं की कमी के अलावा क्या होता है?
डेटाबेस के लिए पर्याप्त कनेक्शन नहीं हो सकता है। फ्रंटएंड और प्रोसेसर प्रक्रियाओं के साथ सर्वरों की संख्या बढ़ रही है - आप उन्हें आसानी से विकसित कर सकते हैं - आपके प्रोसेसर पूल लगातार कनेक्शन का उपयोग करते हैं, अपने जीवन के दौरान वे जल्दी से प्रत्येक डेटाबेस के लिए एक कनेक्शन उदाहरण प्राप्त करते हैं - अप।
आप एक सीमा में भाग गए। और वह, वैसे, बस आपके विन्यास में नहीं खड़ा है।
यदि आप इस तथ्य के लिए अग्रिम रूप से तैयार नहीं हैं कि अब कनेक्शन की कमी होगी, तो कनेक्शन को लागू करना अप्रिय होगा मक्खी पर पूलिंग बहुत आसान नहीं है।
यह बस डिस्क स्थान से बाहर हो सकता है, और प्रक्रिया लॉग में कुछ लिखने के प्रयास में चलेगी :-) ठीक है, फिर से, सामान्य रूप से, प्रक्रियाओं के बारे में - एक सामान्य कारण, हाँ।
ऐसा होता है कि बस किसी कारण के लिए, अनुरोध हैंडलर शुरू किए जाते हैं, और किसी कारण से, अनुरोध उन तक नहीं पहुंचते हैं। इसलिए अचानक यह स्पष्ट नहीं है कि आपकी तकनीक में एक अनियमित सूक्ष्म बग की खोज कहाँ हुई है।
यहां तक कि सेवा पर भार में एक चिकनी वृद्धि के दौरान, इस तरह की एक अजीब बात पैदा हो सकती है - आपका फ्रंटेंड (कहते हैं, नेग्नेक्स) कॉन्फ़िगर किया गया है ताकि जब यह एक निश्चित समय अंतराल एक्स के लिए एक सर्वर से एक निश्चित संख्या में वाई टाइमआउट प्राप्त करे, तो यह समय के दौरान फिर से वहां जाने की कोशिश नहीं करता है। ।
तो आप या आपके व्यवस्थापक ने इन मापदंडों और टाइमआउट को Nginx में कॉन्फ़िगर किया है ताकि पहले सब कुछ चोट लगी हो - और अब अनुरोधों का एक महत्वपूर्ण हिस्सा टाइमआउट में थोड़ा फिट नहीं होता है, और Nginx आपको सर्वर द्वारा डिस्कनेक्ट करता है।
डिस्कनेक्ट किए गए सर्वर से अनुरोध अभी भी सक्रिय हैं, इसलिए लगभग निश्चित रूप से एक स्नोबॉल सभी सर्वरों को बंद कर देगा।
बहुत सी चीजें, सामान्य रूप से होती हैं। मुझे नहीं लगता कि मैं अपने पुनर्वित्त के लिए भी सभी कारणों को याद रख सकता हूं, और निश्चित रूप से मैं पूरी सूची नहीं बना सकता।
यह महत्वपूर्ण है कि नंगे सर्वर का प्रदर्शन दुर्लभ है।
और अन्य ठंडे कारण जो मैं आपको टिप्पणी में लिखने का सुझाव देता हूं :-)
अब थोड़ा PostgreSQL के बारे में - शीर्षक संकेत - और वास्तविक 8 फरवरी के बारे में।
उस दिन हमने एक नया फीचर लॉन्च किया,
सर्फिंगबर्ड टीवी । विचार सरल है - ये वही सिफारिशें हैं जिनकी आपको रुचि हो सकती है, लेकिन केवल वीडियो के बीच।
ऐसा आलसी टीवी :-)
प्रत्येक लिंक की श्रेणियों की सूची एक
इंट्रैस में संग्रहीत की जाती है, और निश्चित रूप से, क्षेत्र के लिए एक
गिस्ट इंडेक्स बनाया गया है। अनुरोध में, क्रमशः, एक हिस्सा है a la
AND site_cats && user_cat
-, यानी कि कम से कम एक ब्याज का एक चौराहा होना चाहिए।
user_cat
उपयोगकर्ता के हितों में से एक यादृच्छिक रूप से चयनित है। हम एक साथ सभी हितों के साथ चौराहे पर नमूना नहीं करते हैं, ताकि जारी करना सभी हितों के लिए एक समान हो, और तीन तिमाहियों के लिए नहीं - डेटाबेस में तीन सबसे लोकप्रिय हितों के लिए, बाकी - जो हुआ उसके लिए।
एक लंबे समय के लिए, हमारे सभी वीडियो स्वचालित रूप से एक अदृश्य "गुप्त" श्रेणी के साथ चिह्नित किए गए थे, इसलिए सर्फिंगबर्ड टीवी के लिए क्वेरी को अंतिम रूप देना मुश्किल नहीं था, हमने सिर्फ एक "फ़िल्टर" वहां जोड़ा:
AND site_cats @> filter_cats
। यही है, लिंक श्रेणियों में फ़िल्टर से श्रेणियां शामिल हैं।
कोड में सशर्त बयानों का उत्पादन नहीं करने के लिए, डिफ़ॉल्ट फ़िल्टर एक खाली सरणी था।
हमारे पास श्रेणियों के बिना कोई लिंक नहीं है, इसलिए डिफ़ॉल्ट स्थिति तुच्छ थी।
लेकिन! किसी कारण के लिए, इस तरह की एक क्वेरी सूचकांक से बाहर हो गई और तालिका के अनुसार Seq स्कैन किया (अर्थात, मैंने इसे लाइन द्वारा सभी पंक्ति को पढ़ा और इसे सूचकांक के बजाय "हाथों से" फ़िल्टर किया)।
तो हम लेट गए। हमने कोड को वापस ले लिया, अपने हाथों से डेटाबेस में खराब प्रश्नों को मार डाला, सशर्त बयानों का एक गुच्छा लिखा, बाहर रखी।
सब ठीक लगने लगा है। एक दर्जन मिनट बीत गए - फिर से हम झूठ बोलते हैं। हम डेटाबेस को देखते हैं - यह उसी के बारे में है। क्या बकवास ..., क्या हम परेशान हैं?
यह पता चला है:
प्रारंभिक प्रश्न जैसे
... site_cats && '{42}'::int[]
ठीक काम करते हैं।
अनुरोध
... site_cats && '{42}'::int[] AND site_cats @> '{}'::int[]
Seq स्कैन पर जाएं, क्योंकि यह थोड़ा पहले पता चला था।
क्वेरीज़
... site_cats && '{42}'::int[] AND site_cats @> '{255}'::int[]
ठीक काम करते हैं।
अनुरोध
... site_cats && '{255}'::int[] AND site_cats @> '{255}'::int[]
फिर से Seq स्कैन पर जाएं! यह पहले से ही काफी आश्चर्यजनक है।
और हाँ,
... site_cats && '{255}'::int[]
ठीक काम करता है।
खैर, पहले उन्होंने एक बैसाखी में डाल दिया, फिर उन्होंने सशर्त बयान, सभी प्रकार की अपमानजनक टिप्पणियां भी लिखीं, और अब लेट नहीं हुईं। इस कारण से :-)
वैसे, केवल सर्फ को नीचे रखा गया था - क्योंकि सर्फ पर,
हमारे बटन की वापसी और बाकी साइट पर हमारे पास अलग-अलग प्रक्रिया पूल हैं। लोड की बहुत अलग प्रकृति को देखते हुए, यह हमें बहुत मदद करता है।
PS कहीं पोस्ट के दूसरे तीसरे में (मैंने 3 रातों के क्षेत्र में लिखा था), पूर्वावलोकन ने काम करना बंद कर दिया - ठीक है, सामान्य तौर पर, हैबर, क्योंकि 500। मुझे आश्चर्य है कि क्या कारण है :-)