2009-09-24 14 views
7

होस्ट करने का सही तरीका मेरे पास एक ऐसा एप्लिकेशन है जो कुछ चीजों की एसिंक्रोनस प्रोसेसिंग के लिए एमएसएमक्यू का उपयोग करता है।* स्थिर * डब्ल्यूसीएफ एमएसएमक्यू विंडोज सेवा

मैं क्यूईएफ पर क्यूई पर संदेश डालने के लिए डब्ल्यूसीएफ का उपयोग करता हूं और संदेश प्राप्त करने और उनके साथ सौदा करने के लिए डब्ल्यूसीएफ एमएसएमक्यू श्रोता (एक विंडोज़ सेवा) है।

मेरी समस्या यह स्थिर रख रही है। कतार सर्वर (जो एक अलग बॉक्स है) से निपटने के लिए सही तरीका क्या है (उदाहरण के लिए)? दूसरे दिन यह हुआ और सेवा बस वहां बैठी - कोई अपवाद नहीं फेंक दिया गया, यह सिर्फ संदेश प्राप्त करना बंद कर दिया। मैं कतार सर्वर नीचे जाने पर अपवाद फेंकना चाहता हूं और फिर इसे सक्षम होने तक इसे कनेक्ट करने का प्रयास करता हूं।

मैंने यह भी देखा है कि सेवा पर "स्टॉप" निष्पादित करने से अक्सर अंततः बंद होने से पहले इसे थोड़ी देर तक लटका दिया जाता है।

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

वर्तमान में

मैं इस:

(नोट: IMyExampleServiceContract मेरी WCF सेवा अनुबंध है और QueueHandler यह क्या लागू करता है)

namespace xyz.MyExample.MSMQListener 
{ 
    /// <summary> 
    /// The class that handles starting and stopping of the WCF MSMQ Listener windows service. 
    /// It will respond to start and stop commands from within the windows services administration snap-in 
    /// It creates a WCF NetMsmqBinding that watches a particular queue for messaages defined by a contract 
    /// in the ServiceContracts project. 
    /// </summary> 
    public partial class MsmqListenerService : ServiceBase 
    { 
     /// <summary> 
     /// The WCF service host 
     /// </summary> 
     private ServiceHost _serviceHost; 

     /// <summary> 
     /// Defines the maximum size for a WCF message 
     /// </summary> 
     private const long MaxMessageSize = 1024 * 1024 * 1024; // 1 gb 
     /// <summary> 
     /// Defines the maximum size for a WCF array 
     /// </summary> 
     private const int MaxArraySize = 1024 * 1024 * 1024; // 1 gb 

     /// <summary> 
     /// The queue name 
     /// </summary> 
     private readonly string _queueName; 
     /// <summary> 
     /// The queue server 
     /// </summary> 
     private readonly string _queueServer; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="MsmqListenerService"/> class. 
     /// </summary> 
     public MsmqListenerService() 
     { 
      InitializeComponent(); 
      using (ConfigManager config = new ConfigManager()) 
      { 
       _queueName = config.GetAppSetting("QueueName"); 
       _queueServer = config.GetAppSetting("QueueServer"); 
      } 
     } 

     /// <summary> 
     /// When implemented in a derived class, executes when a Start command is sent to the service by the Service Control Manager (SCM) or when the operating system starts (for a service that starts automatically). Specifies actions to take when the service starts. 
     /// <para> 
     /// The logic in this method creates a WCF service host (i.e. something that listens for messages) using the <see cref="IMyExampleServiceContract"/> contract. 
     /// The WCF end point is a NetMSMQBinding to the MyExample MSMQ server/queue. 
     /// It sets up this end point and provides a class to handle the messages received on it. 
     /// The NetMSMQBinding is a Microsoft WCF binding that handles serialisation of data to MSMQ. It is a ms proprietary format and means that the message on the queue 
     /// can only be read by a WCF service with the correct contract information. 
     /// </para> 
     /// </summary> 
     /// <param name="args">Data passed by the start command.</param> 
     protected override void OnStart(string[] args) 
     { 
      try 
      { 
       Logger.Write("MyExample MSMQ listener service started.", StandardCategories.Information); 

       Uri serviceUri = new Uri("net.msmq://" + QueueServer + QueueName); 

       NetMsmqBinding serviceBinding = new NetMsmqBinding(); 
       serviceBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None; 
       serviceBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None; 
       serviceBinding.MaxReceivedMessageSize = MaxMessageSize; 
       serviceBinding.ReaderQuotas.MaxArrayLength = MaxArraySize; 

       //QueueHandler implements IMyExampleServiceContract 
       _serviceHost = new ServiceHost(typeof(QueueHandler)); 
       _serviceHost.AddServiceEndpoint(typeof(IMyExampleServiceContract), serviceBinding, serviceUri); 

       _serviceHost.Open(); 
       Logger.Write("MyExample MSMQ listener service completed OnStart method.", StandardCategories.Information); 
      } 
      catch (Exception ex) 
      { 
       ExceptionReporting.ReportException(ex, "DefaultExceptionPolicy"); 
       throw; 
      } 
     } 

     /// <summary> 
     /// Gets the name of the queue to send to. 
     /// This is retrieved from the application settings under QueueName 
     /// </summary> 
     private string QueueName 
     { 
      get { return _queueName; } 
     } 

     /// <summary> 
     /// Gets the name of the queue server to send to. 
     /// This is retrieved from the application settings under QueueServer 
     /// </summary> 
     private string QueueServer 
     { 
      get { return _queueServer; } 
     } 

     /// <summary> 
     /// When implemented in a derived class, executes when a Stop command is sent to the service by the Service Control Manager (SCM). Specifies actions to take when a service stops running. 
     /// </summary> 
     protected override void OnStop() 
     { 
      if (_serviceHost != null) 
      { 
       _serviceHost.Close(); 
       _serviceHost = null; 
      } 
     } 

     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     public static void Main() 
     { 
      //Code will have to be compiled in release mode to be installed as a windows service 
      #if (!DEBUG) 
       try 
       { 
        Logger.Write("Attempting to start queue listener service.", StandardCategories.Information); 
        ServiceBase[] ServicesToRun; 
        ServicesToRun = new ServiceBase[] 
          { 
          new MsmqListenerService() 
          }; 
        ServiceBase.Run(ServicesToRun); 
        Logger.Write("Finished ServiceBase.Run of queue listener service.", StandardCategories.Information); 
       } 
       catch (Exception e) 
       { 
        ExceptionReporting.ReportException(e, "DefaultExceptionPolicy"); 
        throw; 
       } 
      #else 
       //This allows us to run from within visual studio 
       MsmqListenerService service = new MsmqListenerService(); 
       service.OnStart(null); 
       System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); 
      #endif 

     } 
    } 
} 

उत्तर

5

मैं क्यों आपकी सेवा मेजबान व्यतीत कर रहा है यकीन नहीं है, लेकिन मैं निश्चित रूप से चीजों की एक जोड़ी के बारे में सोच सकते हैं इसे और अधिक विश्वसनीय बनाने के लिए प्रयास करने के लिए:

  • मैं सेवा मेजबान के Faulted event में हुक करने के लिए सुनिश्चित करें चाहते हैं। आमतौर पर यह पहचानने के लिए एक अच्छी जगह है कि आपको अपने मेजबान को फिर से राहत देने की आवश्यकता है।
  • मैं रिमोट कतार सर्वर पर एक विशेष स्वास्थ्य-स्थिति कतार रखने के द्वारा स्वयं को पिंग करने के लिए एक तरीका स्थापित करता हूं और उस कतार पर दूसरी कस्टम डब्ल्यूसीएफ सेवा सुनता हूं। तब मैं सेवा मेजबान बस नियमित रूप से है कि कतार में संदेशों आग है और जाँच लें कि चाहते हैं:

क) यह उन्हें सफलतापूर्वक भेज सकते हैं और

ख) कि संदेशों उठाया जा रहा है और संसाधित द्वारा स्थानीय क्यूसीएफ स्वास्थ्य सेवा उस कतार पर सुन रही है। इसका उपयोग कुछ संभावित त्रुटि स्थितियों का पता लगाने के लिए किया जा सकता है।

+0

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

+0

ईमानदार होने के लिए, मुझे बस निश्चित रूप से पता नहीं है, इसलिए मैंने दोनों विकल्पों की सिफारिश क्यों की :) – tomasr

3

अंतर्निहित डब्ल्यूसीएफ एमएसएमक्यू श्रोता शायद आपके कोड तक पहुंचने से पहले एक अपवाद फेंक रहा है। जो निराशाजनक स्थिति है क्योंकि ऐसा लगता है कि कुछ भी नहीं होता है और आपका संदेश खराब हो जाता है। अपनी सेवा कॉन्फ़िगरेशन फ़ाइल में WCF service tracing चालू करें।

अब जब आप अपनी सेवा चलाते हैं तो यह पता लगाएगा और आपको अधिक जानकारी देगा। एक्सएमएल के माध्यम से अपनी आंखों को दबाए रखने के बजाय एमएस सर्विस ट्रेस व्यूअर के साथ इस लॉग फ़ाइल को लाएं।

जब मैं इस समस्या को मैं "System.ServiceModel.ProtocolException" हो रही थी था:

कोई इनकमिंग MSMQ संदेश निहित अवैध या अप्रत्याशित नेट अपने शरीर में जानकारी निर्धारण संदेश। संदेश प्राप्त नहीं किया जा सकता है। सुनिश्चित करें कि प्रेषक मिलान सत्र * के साथ एक संगत सेवा अनुबंध का उपयोग कर रहा है। मेरा सेवा अनुबंध बदल गया है विशेषताएँ सत्र मोड = सत्र मोड। आवश्यक है, लेकिन ग्राहक लेनदेन के साथ संदेश नहीं भेज रहे थे।

+0

विचार के लिए धन्यवाद, मैं ट्रेसिंग चालू कर दूंगा और इसे जाने दूंगा। – David

1

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

यदि आप मैन्युअल रूप से अपनी कतार को संसाधित करते हैं तो आप & पर क्या देख रहे हैं, यह देखने में सक्षम होंगे कि MessageQueueExceptions को फेंक दिया गया है, उदा। आप MessageQueueErrorCodes जैसे QueueNotFound या MachineNotFound को पकड़ने में सक्षम होंगे।

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

डब्ल्यूसीएफ का उपयोग करने का मुख्य लाभ यह है कि आप निरंतर चल रहे विंडोज सेवा के बजाय वेब अनुप्रयोग को तुरंत चालू करने के लिए WAS का उपयोग कर सकते हैं। यदि आप इस लाभ का उपयोग नहीं कर रहे हैं तो मुझे वास्तव में डब्ल्यूसीएफ को कोई लाभ नहीं दिखता है - यह सिर्फ स्पर्श करने और देखने के लिए आपको बहुत कुछ बता रहा है।


बस एक साइड नोट के रूप में; शायद आप यह जांच सकते हैं कि जब आप कतार पर संदेश डाल रहे हैं तो सर्वर उपलब्ध है या नहीं? यदि सर्वर कतार पर संदेश डालने के लिए उपलब्ध है तो श्रोता तुरंत उन्हें संसाधित करने में सक्षम होगा।

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