3

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

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

我在实施 MSMQ 后看到的内容:

  • 我将日志发送到 MSMQ 的应用程序几乎立即返回(而不是等待提交日志),这正是我想要的。
  • 尽管我在不到 30 秒的时间内向 MSMQ 应用程序发送了 1000 条日志,但所有 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 年)并且很难阅读。也许他们希望我对这个主题有一些基本的知识水平。

4

1 回答 1

1

您所看到的(如果您在 WCF 上使用 net.msmq 绑定)就是设计要发生的。

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

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

如果性能次优,您可以更改 WCF 限制设置,以在您的服务行为中允许更多并发连接。

例如

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

于 2011-05-16T22:12:39.243 回答