2015-01-08 83 views
1

我有一個通過WCF和MSMQ運行的特定服務。 一切工作正常,但我們有這個要求,說如果在一個工作的處理期間發生意外事件,它不應該影響任何其他。 該服務的設計是健壯的,它是。我們從未在兩個運營中發生過崩潰,但是最近我們的客戶喜歡殺死服務流程並抱怨失去了一個以上的工作。從MSMQ中刪除多條消息

爲了調查我已經添加了一個計時器,每200ms跟蹤隊列的內容並發現一些意外的事情。 處理請求時,WCF會從隊列中刪除多條消息。 下面是相關事件的smartinspec跟蹤(在中間一欄的數字是線程id):

enter image description here

它似乎總是保持在服務過程中某處緩衝的一個消息。 我一直在尋找通過WCF文檔,我還沒有發現任何此行爲的參考 有什麼我可以做,以防止這種緩衝或你可以引用我的一些相關的文章?

這裏的服務類:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)] 
public class TheService : ITheService 
{ 
    private readonly ITraceFacade trace = TraceFactory.Resolve();//for tracing 

    public ClientCodeWrapper clientCodeWrapper { get; set; }// a wrapper for libraries written by our client. it's instantiated and set in the OnStart method of the service host class 

    public void ProcessJob(long jobId) 
    { 
     using (this.trace.ActivityScope(string.Format(CultureInfo.InvariantCulture, "The Service.ProcessJob({0})", jobId))) 
     {   
     this.clientCodeWrapper.ProcessJob(jobId);   
     } 
    }  
} 

,這是你看到的似乎剛剛有望我,我的服務配置

<system.serviceModel> 
    <bindings> 
    <netMsmqBinding> 
     <binding name="MsmqBindingNonTransactionalNoSecurity" exactlyOnce="false"> 
     <security mode="None"/> 
     </binding> 
    </netMsmqBinding> 
    </bindings> 

    <services> 
    <service name="TheService"> 
     <host> 
     <baseAddresses> 
      <add baseAddress="http://localhost:8080/TheServiceIn" />   
     </baseAddresses> 
     </host>   
     <endpoint address="net.msmq://localhost/private/TheServiceIn" 
       binding="netMsmqBinding" 
       bindingConfiguration="MsmqBindingNonTransactionalNoSecurity" 
       contract="ITheService">   
     <identity> 
      <dns value="localhost"/> 
     </identity> 
     </endpoint>  

     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
    </service> 
    </services> 
</system.serviceModel> 
+0

我以前遇到過這種行爲。你無能爲力。這就是netMsmqBinding堆棧的工作原理。 –

回答

2

。確實,WCF可以讀取隊列中的多條消息進行處理。通常情況下,這不是問題,對於事務隊列,這絕對不是問題(因爲每個單獨的事務只會在消息處理完成後才提交,否則事務將中止並且消息返回隊列) 。

因此,基本上,您選擇停用正在處理消息的方式,通過禁用事務並使用非事務性隊列來避免丟失消息。基本上你告訴MSMQ和WCF,偶爾會丟失消息是完全可以的。

考慮一下如果你的機器(或MSMQservice)崩潰會發生什麼:你不會失去一個工作;你會失去所有這些,因爲消息不會被持續。

+0

同意,儘管啓用事務性排隊有一個缺點,即他的客戶將不再能夠*殺死服務*來刪除阻止處理的消息。 –

+0

@TomRedfern我不認爲這會是一個問題,但感謝分享這個問題。 –

+0

我已經將此標記爲正式答案,因爲跨國隊列確實有效。 但是我們選擇不改變軟件,因爲事務範圍會干擾我們的sql事務。 –