2013-04-11 154 views
0

我與傳統的Windows服務讀取專用MSMQ隊列中的消息的工作處理它們(做一些數據庫的工作,發送一些電子郵件),然後等待下一條消息(PeekCompleted)MSMQ,Windows服務和服務器重新啓動

服務有問題 - 無論何時Windows Update需要服務器重新啓動(幾乎總是如此),服務將以「已啓動」狀態恢復,但必須手動重新啓動或消息只是堆積在隊列中。

我的第一個想法是認爲OnStart處理程序中有某些東西在服務器恢復時沒有被擊中,我試圖理清日誌(另一個故事),但Windows服務和線程不是我正常的域名,所以我希望有人可以指向我在正確的方向......

下面是OnStart處理程序和消息處理函數,剝奪無關緊要的東西。

問題:在OnStart中,MessageRecieved函數附加到PeekCompleted事件。 我假設OnStart在服務器重新啓動時觸發,因此處理程序必須連接,但我不清楚(a)重新啓動期間已經在隊列中的消息或(b)在重新啓動期間到達的消息是否會實際觸發事件 ?

如果應該還有別的東西我應該找?

歡迎任何建議!前排隊的基礎設施已經啓動並全面運作

protected override void OnStart(string[] args) 
    { 
     try 
     { 
      _inProcess = false; 
      _queueMessage = null; 
      _stopping = false; 
      _queue = ReadyQueue(_queueName); 
      if (_queue == null) 
      { 
       throw new Exception(string.Format("'ReadyFormQueue({0})' returned null", _queueName)); 
      } 
      _queue.PeekCompleted += new PeekCompletedEventHandler(MessageReceived); 
      _queue.Formatter = new BinaryMessageFormatter(); 
      _queue.BeginPeek(); 
     } 
     catch (Exception exception) 
     { 
      //do cleanup and other recovery stuff 
     } 
    } 


    private void MessageReceived(object sender, PeekCompletedEventArgs e) 
    { 
     _currentMessage = null; 
     _inProcess = false; 
     try 
     { 
      _queueMessage = _queue.EndPeek(e.AsyncResult); 
      _queueMessage.Formatter = new BinaryMessageFormatter(); 
      _currentMessage = (MyMessageType)_queueMessage.Body; 
      _queue.ReceiveById(_queueMessage.Id); 
      _inProcess = true; 
      _helper = new MessageHelper(); 
      _currentMessage = _helper.Process(_currentMessage); //sets global _inProcess flag 
      if (_inProcess) 
      { 
       Thread.Sleep((int)(_retryWaitTime * 0x3e8)); 
       SendFormMessageToQueue(FailedQueueName, _currentMessage); 
      } 
      else 
      { 
       _queue.BeginPeek(); 
      } 


     } 
     catch (Exception exception) 
     { 
      _inProcess = false; 
      //do other recovery stuff 
      if (_currentMessage != null) 
      { 
       ReadyFormQueue(_poisonQueueName); 
       SendFormMessageToQueue(_poisonQueueName, _currentMessage); 
      } 
     } 
    } 

回答

1

這舊的Windows服務可以啓動,必須​​在初始連接失敗,因此沒有處理消息。

我會檢查的第一件事(除非windows服務具有正確的日誌記錄)是否存在正確設置的Windows服務依賴關係 - 您不希望您的傳統服務完全啓動,直到MSMQ服務本身完全開始。

我不認爲每個說的遺留服務有問題,因爲一旦你重新啓動它,它似乎工作正常,我認爲你有一個資源可用競賽類型的問題,其中消費者開始之前資源並沒有完全從中恢復。

我會:創建一個服務依賴關係(可以在SCM中完成),然後重新啓動服務器,看看是否有更多的MSMQ消息起來,我猜測答案是否定的。

希望這有助於

+0

感謝看起來像問題!我已經將服務設置爲「自動延遲」(它本應該放在第一位),但要設置依賴項,我的理解是必須在服務安裝項目中進行配置 - 除非我丟失了某些內容 - 「依賴項」選項卡在SCM對話框中,如果安裝程序沒有設置依賴關係,則禁用,是的? – Serexx

+0

是的,這可能是一個OnInstall進程 - 您可能無法通過SCM訪問它,但可能是荒謬的。 –