Question

I have an interesting situation on my hands. For a few years now we've had a WCF service that runs on an IIS box on our network that we use for logging. Applications use basicHttpBinding to send log messages and it logs them to a database. Most of the logging from all other applications is limited to a few dozen logs per operation. Recently we've ported another application to use this logging service. This application logs quite a bit more aggressively than any of the other clients for our logging service. It has an operation that during its course could log over 100,000 messages (this is for importing 100,000 records via CSV file).

In trying to find a way to make this run more efficiently it was suggested that I try MSMQ to queue the log requests and forward them on to the service instead of having the application communicate directly with the logging service (the request was being sent in a separate thread for performance purposes). In this way the application isn't blocked while the log is being written. I have implemented a proof of concept for this MSMQ solution on my local machine but as I have never used MSMQ before, and as I am only now learning what its place is technologically, I'm finding myself with a lot of questions and few answers. I'm hoping someone can point me to some concise information on how MSMQ works so that I can better debug this proof of concept I have written.

What I'm seeing after implementing MSMQ:

  • My application that sends the logs to MSMQ returns almost immediately (rather than waiting for the log to be committed) which is what I want.
  • Even though I sent 1000 logs to the MSMQ application in fewer than 30 seconds, it takes several minutes for all 1000 logs to make it to the database. It appears as though my queue has some sort of throttling enabled where it is holding back the log requests but I don't know how / where to check that.
  • If I use net.tcp on the server receiving the logs from the MSMQ service I get a ton of service timeout errors and only 90% (or so) of the logs make it to the database but if I use basicHttpBinding it works reliably.

Here is the code in my MSMQ service:

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

}

Here is the code of me creating the MSMQ service

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();
}

Here is the code in the application I use to call the MSMQ service:

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

I appreciate any help someone can provide. I'm a little lost on exactly what set of features are available to me using MSMQ. I have done 6 or so hours of research via google. Most docs I have found are pretty old (2007) and are a tough read. Perhaps they are expecting me to have some baser level of knowledge on the subject.

Was it helpful?

Solution

What you're seeing (if you're using net.msmq binding on your WCF) is what is designed to happen.

MSMQ, as a store-and-forward facility, will store messages in a queue at the sending client and the receiving server until either network or processing bandwidth is available. What this does is take load off the client (as you've observed) by making the process asynchronous.

You can view the statuses of the queues using Performance Monitor, the number of messages in the outbound queue (at the client) and the server queue are written to performance counters in realtime and can be viewed and/or logged.

If the performance is sub-optimal, you could look to change the WCF throttling settings to allow more concurrent connections in your service behaviour.

e.g.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top