2011-05-16 176 views
3

我手上有一個有趣的情況。幾年來,我們已經有了一個WCF服務,它運行在我們網絡上用於記錄日誌的IIS框中。應用程序使用basicHttpBinding發送日誌消息,並將它們記錄到數據庫中。來自所有其他應用程序的大部分日誌記錄僅限於每次操作幾十個日誌。最近我們已經移植了另一個應用程序來使用這個日誌服務。此應用程序比我們的日誌記錄服務的其他任何客戶端都積極地進行日誌記錄。它的操作過程中可以記錄超過100,000條消息(這是通過CSV文件導入100,000條記錄)。通過MSMQ緩存到WCF Web服務

在試圖找到一種更高效運行的方法時,建議我嘗試MSMQ排列日誌請求並將它們轉發到服務,而不是讓應用程序直接與日誌服務通信(請求爲了性能目的,在單獨的線程中發送了)。這樣,在寫入日誌時應用程序不會被阻塞。我在本地機器上實現了MSMQ解決方案的概念證明,但是因爲我之前從未使用過MSMQ,而且現在我只知道它的技術位置,所以我發現自己有很多問題並且答案很少。我希望有人能指點我一些關於MSMQ如何工作的簡明信息,以便我可以更好地調試我寫過的這個概念證明。

我執行後MSMQ看到什麼:

  • 我的應用程序發送的日誌 MSMQ返回幾乎立即 (而不是等待日誌 承諾),這是我想要的。
  • 即使我發1000個日誌,在不到30 秒 MSMQ應用程序,它需要幾分鐘的時間 所有1000個日誌,以使其對 數據庫。看起來好像我的 隊列有某種節流 啓用它阻止 日誌請求,但我不知道如何/在哪裏檢查。
  • 如果我在從MSMQ服務接收日誌的服務器上使用net.tcp,我得到大量的服務超時錯誤,只有90%(左右)的日誌使它到數據庫,但如果我使用basicHttpBinding,可靠。

這裏是我的MSMQ服務的代碼:

public void QueueLog(Log log) 
{ 
    try 
    { 
     ServiceClient writeLog = getLoggingService(); 

     string exceptionText = log.Exception == null ? string.Empty : log.Exception.ToString(); 
     writeLog.WriteCompatibleLog(log.LoggerName, (LoggingService.Logging.LogType)log.LogType, exceptionText, log.Message, log.ApplicationName, Utility.GetAssemblyVersion(Assembly.GetCallingAssembly()), 
      Utility.GetFirstIPAddress(), Utility.GetHostName(), log.Category); 
    } 
    catch (Exception ex) 
    { 
     Debug.WriteLine("LoggingServiceWrapper.DotNet Error\n\n" + ex.GetBaseException().Message + "\n\n" + ex.GetBaseException().StackTrace); 
    } 
} 

private ServiceClient getLoggingService() 
{ 
    return new ServiceClient(new BasicHttpBinding(), new EndpointAddress("http://MyServer/Service.svc")); 

} 

這裏是我的創建MSMQ服務

if (!MessageQueue.Exists(Properties.Settings.Default.QueueName)) 
{ 
    MessageQueue.Create(Properties.Settings.Default.QueueName, true); 
} 

ServiceHost serviceHost = new ServiceHost(typeof(LoggingServiceQueue.LoggingServiceQueue), new Uri(Properties.Settings.Default.Address)); 
{ 
    serviceHost.Open(); 

    Console.ReadLine(); 

    serviceHost.Close(); 
} 

下面的代碼是我用來調用應用程序的代碼MSMQ服務:

LoggingServiceQueueClient client = new LoggingServiceQueueClient(new NetMsmqBinding(NetMsmqSecurityMode.None), new EndpointAddress("net.msmq://localhost/private/Logging")); 

client.QueueLog(new LoggingServiceQueue.Log 
{ 
    LoggerName = loggerName, 
    LogType = (LoggingServiceQueue.LogType)logType, 
    ApplicationName = applicationName, 
    Category = category, 
    Exception = exception, 
    Message = message, 
    SourceHostName = Utility.GetHostName(), 
    SourceIp = Utility.GetFirstIPAddress(), 
    Version = Utility.GetAssemblyVersion(callingAssembly) 
}); 

我很感激任何幫助,所以meone可以提供。我對使用MSMQ可以使用哪些功能有點遺憾。我通過谷歌完成了6個小時的研究。我發現的大多數文檔都很老(2007),並且很難讀。也許他們希望我對這個主題有一些基礎知識。

回答

1

你所看到的(如果你在你的WCF上使用net.msmq綁定)是設計要實現的。

作爲存儲轉發功能,MSMQ將郵件存儲在發送客戶端和接收服務器的隊列中,直到網絡或處理帶寬可用。這樣做是通過使進程異步來減輕客戶負擔(如你所見)。

您可以使用性能監視器查看隊列的狀態,出站隊列(客戶端)中的消息數量和服務器隊列實時寫入性能計數器,並且可以查看和/或記錄。

如果性能不是最佳,您可以考慮更改WCF限制設置,以允許在您的服務行爲中使用更多併發連接。

例如

<serviceThrottling 
     maxConcurrentCalls="20" 
     maxConcurrentSessions="20" 
     maxConcurrentInstances="20" 
     /> 

+0

你知道什麼性能開銷應該是像到本地MSMQ服務進行通信?我會想象,因爲卸載處理是它的主要目的,所以它會很快。 上面提到的服務限制,你是建議爲Web服務還是MSMQ服務? – omatase 2011-05-16 23:04:04

+0

對於客戶端來說,開銷應該在10毫秒左右,因爲沒有等待需要響應。如果您通過MSMQ公開它,則應該在WCF服務端點應用調節參數。 – DaveRead 2011-05-17 07:33:36

+0

這裏一定是錯的。 100,000個日誌請求在不到一小時的時間內成功排隊,但是MSMQ應用程序在10個小時後仍然向WCF服務發送日誌!我知道日誌使它快速到MSMQ應用程序,所以這不是問題。由於某些原因,儘管MSMQ應用程序不想盡可能快地推送日誌。我知道瓶頸不是其他服務器上的WCF日誌記錄服務。在沒有MSMQ的情況下,100,000條日誌條目發生的速度要快得多。 – omatase 2011-05-17 18:02:24