Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过MSMQ到WCF Web服务的日志缓冲_Wcf_Msmq_Netmsmqbinding_Msmq Wcf - Fatal编程技术网

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

通过MSMQ到WCF Web服务的日志缓冲,wcf,msmq,netmsmqbinding,msmq-wcf,Wcf,Msmq,Netmsmqbinding,Msmq Wcf,我手头有一个有趣的情况。几年来,我们已经有了一个WCF服务,它运行在我们网络上用于日志记录的IIS盒上。应用程序使用basicHttpBinding发送日志消息,并将其记录到数据库中。来自所有其他应用程序的大多数日志记录仅限于每个操作几十个日志。最近我们移植了另一个应用程序来使用这个日志服务。对于我们的日志记录服务,这个应用程序比任何其他客户端都更积极地记录日志。它有一个操作,在此过程中可以记录超过100000条消息(用于通过CSV文件导入100000条记录) 为了找到一种更有效地运行日志的方法

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

为了找到一种更有效地运行日志的方法,有人建议我尝试使用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"));

}
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服务的代码

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服务的应用程序中的代码:

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"));

}
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年),读起来很难。也许他们希望我在这方面有一些更基础的知识。

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

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

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

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

e、 g



您知道与本地MSMQ服务通信的性能开销是什么样的吗?我可以想象,由于卸载处理是它的主要目的,它会相当快。您在上面设置的服务限制,您是建议对于web服务还是MSMQ服务?对于客户端,开销应该在10毫秒左右,因为不需要等待响应。如果要通过MSMQ公开WCF服务端点,则应在该服务端点应用节流参数。此处一定有问题。100000个日志请求在不到一小时内成功排队,但是MSMQ应用程序在10小时后仍在向WCF服务发送日志!我知道日志可以很快进入MSMQ应用程序,所以这不是问题所在。出于某种原因,MSMQ应用程序不希望尽快推送日志。我知道瓶颈不是另一台服务器上的WCF日志服务。100000个日志条目比没有MSMQ的情况下发生得快得多。您的服务器如何从队列接收消息?它是在计时器上运行还是在ReceiveCompleted事件上注册为委托?如果对队列使用HTTP绑定或Active Directory身份验证,则与TCP相比,这可能会降低性能。服务器只是在IIS服务器上侦听。当队列接收日志请求时,它只是将日志请求推送到该服务。该服务是一个WCF basicHttpBinding服务,在不通过队列时速度要快得多。看起来,在我的MSMQ服务和机器上的消息队列服务之间的任何东西都在严重限制消息。