Help me optimize this MSMQ service
Our MSMQ service, tends to be a pain in the ass for us.
It halts/locks at times, and feels pretty slow at times.
Can you help optimize it? Would love some good suggestions, with an explanation.
Here is our code. Every queue has it's own Invoker that holds the logic, for that queue.
This code just iterates all queues, takes a message, does the logic, and deletes it at the end.
public void Run(string[] queues)
{
var invokerFactory = new InvokerFactory();
var locator = new TypeLocator();
Communicator.Instance.Start().ContinueWith(z =>
{
Parallel.ForEach(locator.Locate<MessageQueueAttribute>(), x =>
{
if (queues != null && !queues.Contains(x.Attributes.First().QueueName))
return;
// Build the invoker
var invoker = invokerFactory.Build<IMessageQueueInvoker>(x.Type);
// Find the attribute data
var attribute = x.Attributes.First();
// Get the queue
var queue = _messagingService.GetQueue(attribute.QueueName);
// Start a new thread
for (var i = 0; i < attribute.NumberOfHandlers; i++)
{
Task.Factory.StartNew(() => ExecuteTransaction(invoker, attribute, queue), TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent);
}
});
}).Wait();
}
public void Run()
{
Run(null);
}
private void ExecuteTransaction(IMessageQueueInvoker invoker, MessageQueueAttribute attribute, MessageQueue queue)
{
while (true)
{
try
{
// Begin transaction
using (var tx = new MessageQueueTransaction())
{
tx.Begin();
// Fecth message
var message = queue.Receive(TimeSpan.FromSeconds(5), tx);
// Map and invoke
using (var reader = new StreamReader(message.BodyStream))
{
var json = reader.ReadToEnd();
var command = JsonConvert.DeserializeObject(json, attribute.CommandType);
try
{
invoker.Invoke(command, message);
}
catch (Exception ex)
{
_messagingService.Send(string.Format("{0}___failed", attribute.QueueName), command);
OnFaulted(ex, queue.QueueName, json);
}
finally
{
// Finish the transaction
tx.Commit();
}
}
}
}
catch (MessageQueueException msmqEx)
{
if (msmqEx.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
{
OnFaulted(msmqEx, "CORE MSMQ EXCEPTION", string.Empty);
throw;
}
}
}
}
private void OnFaulted(Exception exception, string queueName, string queueItem)
{
RaygunClient.Send(exception, new List<string> { "Findroommate.MSMQ" }, new Dictionary<string, string> { { "QueueName", queueName }, { "QueueMessage", queueItem } });
_systemService.Logger.Log("Findroommate.MSMQ", "MessageQueue Failure", new
{
QueueName = queueName
}, exception);
}
0 comments:
Post a Comment