2011-10-03 11 views
8

परिदृश्य: हमारे पास एक स्प्रिंग प्रबंधित वेब एप्लिकेशन है जो वेबस्पेयर के अंदर चलता है। (स्प्रिंग 3.0.एक्स, डब्ल्यूएएस 7) वेबपैप कम्प्यूटेशनल गहन डीबी रीड ऑपरेशंस को निष्पादित करने के लिए स्प्रिंग के WorkManagerTaskExecutor (10 के थ्रेड पूल आकार के साथ कॉन्फ़िगर किया गया) के माध्यम से वेबस्पेयर के कार्य प्रबंधक का लाभ उठाता है। तो मूल रूप से, उत्पन्न करने के लिए एक अनुरोध आता है, कहें, 10 अलग-अलग दस्तावेज। दस्तावेज़ों को उत्पन्न करने के लिए डेटा एकत्र करने/संसाधित करने के लिए केवल डीबी पढ़ने की आवश्यकता होती है। इसलिए हम मूल रूप से 10 दस्तावेजों को संसाधित करने के लिए 10 धागे उत्पन्न करते हैं और अंत में 10 श्रमिकों से लौटाए गए 10 दस्तावेज इकट्ठा करते हैं और उन्हें मर्ज करते हैं और ग्राहक को एक बड़ी प्रतिक्रिया लिखते हैं। हमने जो पहचाना है वह यह है कि 10 धागे डेटा इकट्ठा/संसाधित कर रहे हैं, जबकि समान डीबी कॉल किए गए समूह हैं। तो हम प्रतिक्रिया के साथ सबसे अधिक निष्पादित डीबी विधियों के आसपास एक पहलू बनाने के लिए क्या आया है। पहलू को सिंगलटन के रूप में कॉन्फ़िगर किया गया है, और पहलू का उपयोग करने वाले कैश को पहलू में स्वचालित रूप से अनुरोध किया जाता है ताकि अनुरोध के लिए सेट किया जा सके ताकि प्रत्येक अनुरोध का अपना कैश हो।एक बहु थ्रेडेड वेब अनुप्रयोग में अनुरोध स्कैन किए गए बीन्स

समस्या: अब इस दृष्टिकोण के साथ समस्या यह है कि जब धागे अपने डीबी कॉल कर रहे हैं और पहलू इंटरजेक्ट कर रहे हैं तो हमें java.lang.IllegalStateException: No thread-bound request found अपवाद मिल रहा है। जो मैं समझता हूं वह पूरी तरह मान्य है क्योंकि अनुरोध संदर्भ के बाहर धागे निष्पादित किए जा रहे हैं।

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

उत्तर

5

मुझे नहीं लगता कि आप इसे सीधे कर सकते हैं। यहां तक ​​कि यदि आप कर सकते हैं, यह थोड़ा बदसूरत होगा। हालांकि, आप एक अद्वितीय अनुरोध पहचानकर्ता उत्पन्न कर सकते हैं (या यहां तक ​​कि - सत्र आईडी का उपयोग करें, लेकिन एकाधिक टैब के साथ सावधान), और प्रत्येक प्रोसेसिंग थ्रेड को पास करें। फिर पहलू उस आईडी को कैश की कुंजी के रूप में उपयोग कर सकता है। कैश भी सिंगलटन होगा, लेकिन Map<String, X> होगा, जहां String आईडी और एक्स आपका कैश परिणाम है।

(स्वयं को उत्पन्न करने के धागे के बजाय) चीजों को आसान संभाल करने के लिए बनाने के लिए, आप @Async तरीकों हो सकता है, और प्रत्येक @Async विधि कैश आईडी अपनी पहली पैरामीटर के रूप में पारित कर दिया हो सकता है।

(बेशक, अपने अतुल्यकालिक तरीकों Future<Result> लौट जाना चाहिए, ताकि आप अनुरोध सूत्र में उनके परिणाम एकत्र कर सकते हैं)

+0

मैं दृष्टिकोण के बारे में सोचा है, लेकिन एक दोष यह है कि मुझे लगता है कि इसे पारित करने के लिए मुझे मजबूर जाएगा अनन्य अनुरोध पहचानकर्ता सभी विधि कॉल (थ्रेड निष्पादन के दौरान) को डाउनस्ट्रीम करता है जिसे मैं कैश करना चाहता हूं। इसके अलावा, कैश थोड़ी देर के बाद बहुत बड़ा नहीं होगा? जो मुझे समय-समय पर प्रबंधित करने के लिए मजबूर करेगा। शायद मैं यहाँ कुछ याद कर रहा हूँ। – r4j1v

+0

शायद एक "थ्रेड निष्पादन संदर्भ" है जिसका उपयोग मैं अपने अद्वितीय अनुरोध पहचानकर्ता को स्टोर करने के लिए कर सकता हूं और इसे स्वयं को पास किए बिना पहलू में पुनर्प्राप्त कर सकता हूं? – r4j1v

+5

मैं इस मुद्दे के आसपास पाने में कामयाब रहा। मैंने 'WorkManagerTaskExecutor' के बजाय' SimpleAsyncTaskExecutor' का उपयोग शुरू किया। लाभ यह है कि 'SimpleAsyncTaskExecutor' कभी भी थ्रेड का पुन: उपयोग नहीं करेगा। यह केवल आधा समाधान है। समाधान का दूसरा आधा 'RequestContextListener' के बजाय' RequestContextFilter' का उपयोग करना है। 'RequestContextFilter' में' setThreadContextInheritable() 'विधि है जो मूल रूप से बाल धागे को मूल संदर्भ प्राप्त करने की अनुमति देगी। – r4j1v

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