2010-08-08 12 views
6

का उपयोग करके "बहुत सारे क्लाइंट" अपवाद से परहेज करते हुए मैं manage.py कमांड पर काम करता हूं जो रिमोट होस्ट की जांच के लिए लगभग 200 धागे बनाता है। मेरा डेटाबेस सेटअप मुझे 120 कनेक्शन का उपयोग करने की अनुमति देता है, इसलिए मुझे किसी प्रकार के पूलिंग का उपयोग करने की आवश्यकता है। मैं अलग धागा का उपयोग कर की कोशिश की है, इसथैंज में डीजेंगो ओआरएम का उपयोग करके और BoundedSemaphore

class Pool(Thread): 
    def __init__(self): 
     Thread.__init__(self)   
     self.semaphore = threading.BoundedSemaphore(10) 

    def give(self, trackers): 
     self.semaphore.acquire() 
     data = ... some ORM (not lazy, query triggered here) ... 
     self.semaphore.release() 
     return data 

की तरह मैं हर चेक-धागा करने के लिए इस वस्तु का उदाहरण पारित लेकिन अभी भी "OperationalError: घातक: माफ करना, पहले से कई ग्राहकों" हो रही है पूल ऑब्जेक्ट के अंदर के बाद init-इंग 120 धागे मुझे उम्मीद है कि केवल 10 डेटाबेस कनेक्शन खोले जाएंगे और थ्रेड मुक्त सेमफोर स्लॉट के लिए इंतजार करेंगे। मैं "रिलीज()" पर टिप्पणी करके उस सेमफोर कार्यों को देख सकता हूं, उस मामले में केवल 10 धागे काम करेंगे और अन्य ऐप समाप्ति तक प्रतीक्षा करेंगे।

जितना मैं समझता हूं, हर धागा डेटाबेस के लिए नया कनेक्शन खोल रहा है भले ही वास्तविक कॉल अलग थ्रेड के अंदर है, लेकिन क्यों? क्या केवल एक धागे के अंदर सभी डेटाबेस प्रश्नों को करने का कोई तरीका है?

+0

वास्तविक डीबी समस्या को खोजने के लिए, मुझे लगता है कि हमें अधिक एसक्यूएल कोड की आवश्यकता है। लेकिन, आप पूरे धागे को क्यों पूल नहीं करते हैं, इसलिए आप उस समय केवल 20-30 ही चलाते हैं? – KillianDS

+0

नमस्ते, मेरी समस्या यह है कि django प्रत्येक थ्रेड के लिए कनेक्शन बनाता है जो किसी भी ओआरएम कोड को स्पर्श करता है, भले ही वास्तविक ओआरएम हेरफेर विभिन्न धागे में होता है। (मैंने पूल के उदाहरण देने के लिए कॉल को छोड़कर अन्य थ्रेड से सभी कोड हटाकर इसे चेक किया है)। तो मेरे मामले में डेटा देने के अलावा कोई एसक्यूएल नहीं है। जब तक मेरे पास कक्षा परीक्षक (थ्रेड): डीफ़ रन (स्वयं): self.getter.give (self.trackers) एक कनेक्शन बनाया जा रहा है (ट्रैकर्स यहां स्ट्रिंग की एक सूची है)। और 120 कनेक्शन की सीमा तक पहुंचने के बाद मेरा डेटाबेस अपवाद देना शुरू कर देता है। – Riz

+0

बीटीडब्ल्यू, मैं इस समस्या को एक तरह से हल करने में सक्षम था - प्रत्येक डीबी अनुरोध के बाद मैन्युअल रूप से कनेक्शन बंद करके, प्रदर्शन स्वीकार्य है, लेकिन मैं अभी भी इस समस्या की जड़ के बारे में उत्सुक हूं। – Riz

उत्तर

13

Django का ORM थ्रेड-स्थानीय चर में डेटाबेस कनेक्शन प्रबंधित करता है। इसलिए ओआरएम तक पहुंचने वाले प्रत्येक अलग थ्रेड का अपना कनेक्शन बन जाएगा। आप देख सकते हैं कि django/db/backends/__init__.py की पहली कुछ पंक्तियों में।

यदि आप डेटाबेस कनेक्शन की संख्या को सीमित करना चाहते हैं, तो आपको वास्तव में ओआरएम तक पहुंचने वाले विभिन्न थ्रेडों की संख्या सीमित करनी होगी। एक समाधान एक ऐसी सेवा को लागू करने के लिए हो सकता है जो समर्पित ओआरएम धागे के पूल में ओआरएम अनुरोधों को प्रस्तुत करता हो। अनुरोधों और उनके परिणामों को और अन्य धागे से प्रेषित करने के लिए आपको कुछ प्रकार के संदेश उत्तीर्ण तंत्र को लागू करना होगा। चूंकि यह एक ठेठ निर्माता/उपभोक्ता समस्या है, इसलिए थ्रेडिंग के बारे में पाइथन दस्तावेज़ों को कुछ संकेत देना चाहिए कि इसे कैसे प्राप्त किया जाए।

संपादित करें: मैंने अभी "django कनेक्शन पूलिंग" के लिए googled किया है। ऐसे कई लोग हैं जो शिकायत करते हैं कि Django उचित कनेक्शन पूल प्रदान नहीं करता है। उनमें से कुछ ने एक अलग पूलिंग पैकेज को एकीकृत करने में कामयाब रहे। PostgreSQL के लिए, मैं pgpool midware पर एक नज़र डालेगा।

+0

मैं दोनों मुद्दों में मैन्युअल कनेक्शन.क्लोस() कॉल के साथ pgpool2 या सेमफोर का उपयोग करके, इस समस्या को दो तरीकों से हल करने में सक्षम था। ओआरएम धागे का पूल मैंने पहले कोशिश की है, लेकिन किसी कारण से Django प्रत्येक थ्रेड के लिए एक नया कनेक्शन बनाता है, भले ही कोई वास्तविक ओआरएम न हो, जैसे ही आप ओआरएम के साथ किसी भी अलग थ्रेड तक पहुंचने का प्रयास करते हैं - यहां नया कनेक्शन आता है। पीएस pgpool एक अच्छा समाधान की तरह लग रहा था, लेकिन मैं केवल इस समस्या का समाधान करने में असमर्थ था, क्योंकि मेरे पास एक लम्बी ऐप है (बहुत छोटे नहीं हैं) और पगपूल नए पूल कनेक्शन प्रदान करने में असमर्थ था क्योंकि वे मेरे ऐप – Riz

+0

द्वारा उपयोग किए गए थे। सवाल यह है कि: क्या आप धागे संदर्भ में Pool.give() कहते हैं? यदि आप किसी ऑब्जेक्ट की विधि का आह्वान करते हैं जो थ्रेड से विरासत में मिलता है कि विधि अभी भी कॉलिंग थ्रेड द्वारा निष्पादित की जाती है, तो आवश्यक नहीं है कि ऑब्जेक्ट से जुड़े थ्रेड द्वारा।यदि मैं आपकी पिछली टिप्पणी को सही तरीके से ऊपर बताता हूं, तो कॉलिंग थ्रेड आपके चेकर थ्रेड हैं। इसका मतलब है कि सभी 200 चेकर थ्रेड एक निजी डीबी कनेक्शन बनाने का प्रयास करते हैं (क्योंकि कनेक्शन थ्रेड-स्थानीय रूप से संग्रहीत होता है)। आपके सेमफोर केवल समानांतर ओआरएम एक्सेस की संख्या को सीमित करते हैं, न कि कनेक्शन की संख्या। –

+0

1.6 या उससे भी अधिक के बाद, हम Django में लगातार कनेक्शन कर सकते हैं, https://docs.djangoproject.com/en/1.8/ref/settings/#conn-max-age पर एक नज़र डालें – dotz

संबंधित मुद्दे