2013-07-02 6 views
10

मेरी समस्या को आसान बनाने के लिए, मैं @Transactionnal विधि CreateUser() के साथस्प्रिंग/RabbitMQ: लेन-देन प्रबंधन

APP1 है:

  • सम्मिलित डेटाबेस में नया उपयोगकर्ता
  • RabbitMQ में async संदेश जोड़ें ताकि उपयोगकर्ता को एक अधिसूचना मेल
  • (संभावित रूप से कुछ अतिरिक्त कोड, लेकिन अधिक नहीं)

RabbitMQ संदेश consummer साथ App2

  • Consummes वास्तविक समय में डाक कतार पर संदेश
  • डेटाबेस
  • में पढ़ें मेल डेटा मेल भेजें

समस्या यह है कि कभी कभी होता है, ऐप 2 ऐप 1 पर भी लेनदेन करने से पहले RabbitMQ संदेश का उपभोग करने का प्रयास करता है। इसका अर्थ है कि App2 डेटाबेस पर मेल डेटा नहीं पढ़ सकता क्योंकि उपयोगकर्ता अभी तक नहीं बनाया गया है।

कुछ समाधान हो सकता है:

    App2 पर
  • उपयोग READ_UNCOMMITED अलगाव स्तर
  • RabbitMQ संदेशों वितरण में कुछ देरी (या consummer पर कुछ RetryTemplate)
  • बदलें जिस तरह से हम ईमेल भेजने जोड़े ...

मैंने देखा है कि वसंत में एक खरगोश ट्रान्सएक्शन प्रबंधक है, लेकिन मुझे समझ में नहीं आता कि यह कैसे माना जाता है ork। लेनदेन हैंडलिंग सामान के आंतरिक हमेशा समझने में थोड़ा मुश्किल लगते हैं और दस्तावेज़ीकरण इतना मदद नहीं करता है।


क्या ऐसा कुछ करने का कोई तरीका है?

  • एक @Transactionnal विधि
  • जब लेनदेन समाप्त होता है में एक RabbitMQ कतार में एक संदेश जोड़ें, संदेश कतार के लिए प्रतिबद्ध है, और परिवर्तन डेटाबेस के लिए प्रतिबद्ध हैं
  • तो संदेश यह है कि डीबी लेनदेन समाप्त होने से पहले उपभोग नहीं किया जा सकता

कैसे? और अगर मैं अतुल्यकालिक संदेशों के बजाय सिंक्रोनस RabbitMQ संदेश भेजता हूं तो उदाहरण के लिए क्या उम्मीद करनी चाहिए? क्या यह थ्रेड को प्रतिक्रिया या कुछ के लिए इंतजार कर देगा? क्योंकि हम विभिन्न उपयोगकेस के लिए सिंक और एसिंक संदेश भेजते हैं।

+0

क्या मैं सही हूँ कि दोनों क्षुधा एक ही कतार से संदेश का उपभोग में उन 2 संचालन नहीं डाल करने के लिए है? – pinepain

+0

नहीं, ऐप 1 ने कतार में संदेश डाले हैं और ऐप 2 उस कतार में संदेश उपभोग करता है –

+0

क्या आपने इस समस्या को किसी भी तरह हल करने का प्रबंधन किया था? मुझे एक ही मुद्दे का सामना करना पड़ रहा है। –

उत्तर

1

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

सही कार्यप्रवाह की तरह App1: createUser -> notifyUser; App2: listenForNotifications

1

मेरे लिए लग रहा है मैं जानता हूँ कि यह देर हो चुकी है, लेकिन मैं समय में @Transactional की मेरी समझ सीमित की वजह से यह एक ही समस्या थी। तो यह किसी और के लिए अधिक है जो आप इस पर ठोकर खा जाते हैं।

डेटाबेस पर डेटा को सहेजने के लिए @ ट्रांसेक्शनल का उपयोग करते समय डेटाबेस में सहेजने के लिए वास्तव में तब तक नहीं होता है जब तक कि विधि वापस नहीं आती है, और जब सहेजने को कहा जाता है।

आपके पास तो अगर

@Transactional(readOnly=false) 
public void save(Object object) { //Object should be one of your entities 
    entityManager.persist(object); //or however you have it set up 
    rabbitTemplate.convertAndSend(message); //again - however yours is 
} 

की तरह एक विधि भी यद्यपि आप कॉल करने से पहले आप कतार पर संदेश डाल, का दृढ़ रहना वास्तव में विधि रिटर्न जब तक नहीं होगा, इस प्रकार के कारण वस्तु पर जारी रहती है विधि रिटर्न से पहले कतार पर रखा जाना चाहिए और डेटा वास्तव में डेटाबेस में है।

@ ट्रान्सएक्शनल विधियों को घोंसला करना संभव है (जो सीधे नहीं है) save() विधि रिटर्न के बाद संदेश को कतार में डाल सकता है। हालांकि आप कतार पर संदेश नहीं डाल सकते हैं और उम्मीद नहीं करते हैं कि इसका उपभोग न किया जाए। एक बार यह खत्म हो गया है। तो यदि आपको आवश्यकता हो तो इसे कतार पर डालने में देरी करें।

यदि आप कतार से एक सिंक तरीके से प्रतिक्रिया प्राप्त करना चाहते हैं। मेरे फ़ंक्शन उदाहरण में - आप यह कर सकते हैं, हालांकि यह केवल डेटा को जारी रखने में अधिक समय लगेगा, क्योंकि यह विधि वापस आने से पहले कार्यकर्ता से प्रतिक्रिया की प्रतीक्षा करेगा और वास्तव में डेटा को जारी रखेगा। (यह भी याद रखें कि एक कतारबद्ध संदेश से प्रतिक्रिया प्राप्त करने में एक टाइमआउट है)।

तो मेरी सलाह एक ही @Transactional

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