通过MSMQ将日志缓冲到WCF Web服务

时间:2011-05-16 21:58:24

标签: wcf msmq netmsmqbinding msmq-wcf

我的手上有一个有趣的情况。几年来,我们已经有了一个WCF服务,它运行在我们用于记录的网络上的IIS盒子上。应用程序使用basicHttpBinding发送日志消息,并将它们记录到数据库中。来自所有其他应用程序的大多数日志记录仅限于每个操作几十个日志。最近我们移植了另一个应用程序来使用这个日志服务。此应用程序比我们的日志记录服务的任何其他客户端更积极地记录。它有一个操作,在其过程中可以记录100,000条消息(这是通过CSV文件导入100,000条记录)。

在尝试找到一种方法使这次运行更有效时,建议我尝试使用MSMQ对日志请求进行排队并将其转发到服务,而不是让应用程序直接与日志服务进行通信(请求被发送到一个单独的线程中)。这样,在写入日志时不会阻止应用程序。我已经在我的本地机器上实现了这个MSMQ解决方案的概念验证,但由于我之前从未使用过MSMQ,而且我现在才知道它在技术上的位置,我发现自己有很多问题和答案很少。我希望有人能指出一些关于MSMQ如何工作的简明信息,这样我就可以更好地调试我写过的这个概念证明。

实施MSMQ后我看到了什么:

  • 我将日志发送到的应用程序 MSMQ几乎立即返回 (而不是等待日志 承诺)这就是我想要的。
  • 即使我发送了1000个日志 MSMQ应用程序不到30个 几秒钟,需要几分钟 所有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)
});

感谢有人提供的任何帮助。我对使用MSMQ可以使用的功能集有点迷失。我通过谷歌进行了大约6个小时的研究。我发现的大多数文档都很旧(2007年)并且阅读起来很难。也许他们希望我对这个问题有一些基础知识水平。

1 个答案:

答案 0 :(得分:1)

你所看到的(如果你在你的WCF上使用net.msmq绑定)就是你想要发生的事情。

MSMQ作为存储转发工具,将消息存储在发送客户端和接收服务器的队列中,直到网络或处理带宽可用。这样做是通过使进程异步来加载客户端(正如您所观察到的)。

您可以使用性能监视器查看队列的状态,出站队列(在客户端)中的消息数量和服务器队列实时写入性能计数器,并且可以查看和/或记录。

如果性能不是最佳,您可以查看更改WCF限制设置以允许更多并发连接进行服务行为。

e.g。

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