2012-12-10 27 views
7

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

एक और विचार लचीलापन है। मुझे पता है कि मैं कतार को और अधिक मजबूत बनाने के लिए एमएसएमक्यू को क्लस्टर कर सकता हूं, लेकिन मैं अलग-अलग सर्वरों पर अपनी सेवा का एक उदाहरण चलाने में सक्षम होना चाहता हूं, इसलिए यदि कोई सर्वर अधिसूचनाओं को क्रैश करता है तो कतार में नहीं बनता है लेकिन दूसरा सर्वर प्रोसेसिंग करता है ।

मैंने एमएसएमक्यू बाध्यकारी के साथ प्रयोग किया है और पाया है कि आपके पास एक ही कतार पर एक सेवा के कई उदाहरण हो सकते हैं, और खुद को छोड़ दिया है, वे उपलब्ध सेवाओं में फैले लोड के साथ राउंड-रॉबिन का एक प्रकार कर रहे हैं । यह बहुत अच्छा है, लेकिन मैं कतार की अनुक्रम खोने को समाप्त करता हूं क्योंकि अनुरोधों को संसाधित करने के लिए अलग-अलग उदाहरण अलग-अलग समय लेते हैं।

मैं प्रयोग करने के लिए एक सरल कंसोल ऐप का उपयोग कर रहा हूं, जो नीचे महाकाव्य कोड डंप है। जब यह चलाए जाने के दौरान मैं इस तरह एक आउटपुट मिलता है:

host1 open 
host2 open 
S1: 01 
S1: 03 
S1: 05 
S2: 02 
S1: 06 
S1: 08 
S1: 09 
S2: 04 
S1: 10 
host1 closed 
S2: 07 
host2 closed 

क्या मैं क्या करना चाहते है:

host1 open 
host2 open 
S1: 01 
<pause while S2 completes> 
S2: 02 
S1: 03 
<pause while S2 completes> 
S2: 04 
S1: 05 
S1: 06 
etc. 

मैं सोचा होगा S2 पूरा नहीं किया है के रूप में, यह अभी भी असफल और संदेश वापस हो सकता है कि यह कतार में प्रसंस्करण कर रहा था। इसलिए एस 1 को कतार के दूसरे संदेश को खींचने की अनुमति नहीं दी जानी चाहिए। मेरी कतार हमें लेनदेन है और मैंने सेवा पर TransactionScopeRequired = true सेट करने का प्रयास किया है लेकिन इसका कोई फायदा नहीं हुआ है।

क्या यह भी संभव है? क्या मैं इसके बारे में गलत तरीके से जा रहा हूं? क्या किसी प्रकार की केंद्रीय सिंक्रनाइज़ेशन तंत्र के बिना फेलओवर सेवा बनाने का कोई और तरीका है?

class WcfMsmqProgram 
{ 
    private const string QueueName = "testq1"; 

    static void Main() 
    { 
     // Create a transactional queue 
     string qPath = ".\\private$\\" + QueueName; 
     if (!MessageQueue.Exists(qPath)) 
      MessageQueue.Create(qPath, true); 
     else 
      new MessageQueue(qPath).Purge(); 

     // S1 processes as fast as it can 
     IService s1 = new ServiceImpl("S1"); 
     // S2 is slow 
     IService s2 = new ServiceImpl("S2", 2000); 

     // MSMQ binding 
     NetMsmqBinding binding = new NetMsmqBinding(NetMsmqSecurityMode.None); 

     // Host S1 
     ServiceHost host1 = new ServiceHost(s1, new Uri("net.msmq://localhost/private")); 
     ConfigureService(host1, binding); 
     host1.Open(); 
     Console.WriteLine("host1 open"); 

     // Host S2 
     ServiceHost host2 = new ServiceHost(s2, new Uri("net.msmq://localhost/private")); 
     ConfigureService(host2, binding); 
     host2.Open(); 
     Console.WriteLine("host2 open"); 

     // Create a client 
     ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress("net.msmq://localhost/private/" + QueueName)); 
     IService client = factory.CreateChannel(); 

     // Periodically call the service with a new number 
     int counter = 1; 
     using (Timer t = new Timer(o => client.EchoNumber(counter++), null, 0, 500)) 
     { 
      // Enter to stop 
      Console.ReadLine(); 
     } 

     host1.Close(); 
     Console.WriteLine("host1 closed"); 
     host2.Close(); 
     Console.WriteLine("host2 closed"); 

     // Wait for exit 
     Console.ReadLine(); 
    } 

    static void ConfigureService(ServiceHost host, NetMsmqBinding binding) 
    { 
     var endpoint = host.AddServiceEndpoint(typeof(IService), binding, QueueName); 
    } 

    [ServiceContract] 
    interface IService 
    { 
     [OperationContract(IsOneWay = true)] 
     void EchoNumber(int number); 
    } 

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
    class ServiceImpl : IService 
    { 
     public ServiceImpl(string name, int sleep = 0) 
     { 
      this.name = name; 
      this.sleep = sleep; 
     } 

     private string name; 
     private int sleep; 

     public void EchoNumber(int number) 
     { 
      Thread.Sleep(this.sleep); 
      Console.WriteLine("{0}: {1:00}", this.name, number); 
     } 
    } 
} 
+0

आप कठिन समय बाध्यकारी WCF के MSMQ के साथ ऐसा करना (http://stackoverflow.com/questions/729612/ordered-delivery-with-netmsmqbinding देखें) होगा। हालांकि आप लेनदेन संबंधी एमएसएमक्यू और कुछ सुलह कोड (डब्ल्यूसीएफ के बिना) का उपयोग कर सकते हैं। –

उत्तर

10

batwad,

आप मैन्युअल रूप से एक सेवा बस बनाने के लिए कोशिश कर रहे हैं। आप मौजूदा का उपयोग करने की कोशिश क्यों नहीं करते?

NServiceBus, MassTransit, ServiceStack

कम से कम MSMQ साथ उन लोगों के काम के 2।

इसके अलावा, अगर आपको पूरी तरह से आदेश की आवश्यकता है तो यह वास्तव में किसी अन्य कारण के लिए हो सकता है - आप एक संदेश भेजने में सक्षम होना चाहते हैं और आप पहले संदेश से पहले निर्भर संदेशों को संसाधित नहीं करना चाहते हैं। आप सागा पैटर्न की तलाश में हैं। NServiceBus और MassTransit दोनों आपको आसानी से सागा प्रबंधित करने की अनुमति देंगे, वे दोनों आपको प्रारंभिक संदेश को ट्रिगर करने और फिर शर्तों के आधार पर शेष संदेशों को ट्रिगर करने की अनुमति देंगे। यह आपको अपने वितरित एप्लिकेशन को एक स्नैप के पंपिंग को लागू करने की अनुमति देगा।

फिर भी आप कोड की एक पंक्ति लिखने के बिना हजारों क्लाइंट, कतार सर्वर और संदेश प्रोसेसर तक पहुंच सकते हैं और न ही कोई समस्या हो सकती है।

हमने यहां एमएसएमक पर अपनी सेवा बस लागू करने की कोशिश की, हमने छोड़ दिया क्योंकि एक और मुद्दा रुक गया। हम NServiceBus के साथ गए लेकिन MassTransit भी एक उत्कृष्ट उत्पाद है (यह 100% खुला स्रोत है, NServiceBus नहीं है)। सर्विसस्टैक एपीआई बनाने और संदेश कतारों का उपयोग करने में बहुत ही बढ़िया है - मुझे यकीन है कि आप इसे ऐसी सेवाएं बनाने के लिए उपयोग कर सकते हैं जो मिनटों में कतार फ्रंट-एंड के रूप में कार्य करते हैं।

ओह, मैं उल्लेख किया है कि एन एस बी और मीट्रिक टन के मामले में दोनों ही कोड के 10 लाइनों के नीचे की आवश्यकता होती है पूरी तरह से कतार, प्रेषकों और संचालकों को लागू करने की?

----- जोड़ा -----

उदी दहन (NServiceBus का मुख्य योगदानकर्ता में से एक) में इस बारे में बात करती: "In-Order Messaging a Myth" by Udi Dahan "Message Ordering: Is it Cost Effective?" with Udi Dahan

क्रिस पैटरसन (मुख्य में से एक सामूहिक ट्रांज़िट के योगदानकर्ता) "Using Sagas to ensure proper sequential message order" question

StackOverflow प्रश्न/उत्तर: "Preserve message order when consuming MSMQ messages in a WCF application"

----- प्रश्न -----

मुझे यह कहना होगा कि मुझे संदेश आदेश की गारंटी देने की आवश्यकता क्यों है, क्या आप एक ही स्थिति में होंगे यदि आप HTTP/SOAP का उपयोग कर रहे थे मसविदा बनाना? मेरा अनुमान नहीं है, तो यह एमएसएमक्यू में एक समस्या क्यों है?

गुड लक, उम्मीद है कि इस मदद करता है,

+0

मैं सूचनाएं जो एक दूसरे पर निर्भर हैं की परवरिश कर रहा हूँ। उदाहरण के लिए, एक ट्रेन एक स्टेशन नहीं छोड़ सकते से पहले ही वहाँ आ गया है। मैं अन्यथा OnDepart हैंडलिंग काम नहीं कर सकते, तो सुनिश्चित करें OnDepart अधिसूचना OnArrive के बाद नियंत्रित किया जाता है बनाना चाहते हैं (उदा: यह काम नहीं कर सका कि ट्रेन ने स्टेशन पर कितनी देर तक खर्च किया था, अगर उसने अभी तक ऑनऑरिव को संभाला नहीं था) – batwad

+0

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

+0

ठीक है, मुझे लगता है कि मुझे अंततः यह मिल गया ... आप ऑनडपर्ट ईवेंट भेज रहे हैं, हालांकि आप चिंतित हैं कि ऑनऑरिव ईवेंट पर ऑनऑरिव इवेंट ट्रिगर हो जाने पर बाद में संसाधित नहीं हो सकता है ... हाँ मुझे समस्या दिखाई दे रही है - लेकिन दुर्भाग्य से मैं वास्तव में आपको शायद एक सुनहरा समाधान नहीं दे सकता: कुछ अद्वितीय पहचानकर्ता का उपयोग करें, अगर आप गारंटी नहीं दे सकते कि एमएसएमक्यू किसी अन्य से पहले एक संदेश भेजता है (ट्रेन मूल नेटवर्क क्रैश इसलिए ऑनडपार्ट वहां फंस गया है, और अंततः ट्रेन आती है) तो आपको इसके चारों ओर कोड करना होगा। यदि आपको ऑनऑरिव ईवेंट मिलता है और ऑनडार्ट –

1

संदेशों की इन-ऑर्डर डिलीवरी सुनिश्चित करना उच्च वॉल्यूम मैसेजिंग के साथ वास्तविक तथ्य वाले चिपचिपा मुद्दों में से एक है।

एक आदर्श दुनिया में, आपके संदेश गंतव्यों को आउट-ऑफ-ऑर्डर मैसेजिंग को संभालने में सक्षम होना चाहिए। यह सुनिश्चित करके यह हासिल किया जा सकता है कि आपके संदेश स्रोत में कुछ प्रकार की अनुक्रम जानकारी शामिल है। फिर आदर्श रूप से यह किसी प्रकार का एक्स-ऑफ-एन बैच स्टैंप (10 का संदेश 1, 10 में से 2, आदि) का रूप लेता है। आपके संदेश गंतव्य को डेटा वितरित करने के बाद डेटा को इकट्ठा करने की आवश्यकता होती है।

हालांकि, असली दुनिया में अक्सर ऑर्डर से आने वाले संदेशों को संभालने के लिए डाउनस्ट्रीम सिस्टम को बदलने के लिए कोई गुंजाइश नहीं है। - वास्तव में आप आमतौर पर 'समूह आईडी' यदि आप एक के लिए-प्रत्येक समूह अर्थ में एकल पिरोया जा सकते हैं, आप अर्थ है जिसका अर्थ है किसी तरह का मिल सकता है

  1. जाओ पूरी तरह से एकल थ्रेड: इस उदाहरण में आपके पास दो विकल्प अभी भी विभिन्न संदेश समूहों में समेकन है।
  2. अपने प्रत्येक उपभोक्ता सिस्टम के आस-पास re-sequencer रैपर लागू करें जो आप इन-ऑर्डर संदेशों को प्राप्त करना चाहते हैं।

न तो समाधान बहुत अच्छा है, लेकिन यही एकमात्र तरीका है जो मुझे लगता है कि आपके पास समेकन और इन-ऑर्डर संदेश वितरण हो सकता है।

+0

दिलचस्प है, लेकिन एक ServerA कतार के बंद संदेश 1 के- 10 लेता है, और ServerB कतार के बंद संदेश 2 के- 10 लेता है, न कभी एक पूरा बैच resequence करने के लिए मिल जाएगा। – batwad

+0

तो इस कॉन्फ़िगरेशन में आपको प्रति समूह एक कतार की आवश्यकता है। यह बहुत व्यावहारिक नहीं है। –