Буферизация журнала через MSMQ для веб-службы WCF
У меня интересная ситуация на моих руках. Вот уже несколько лет у нас есть служба WCF, которая работает на компьютере IIS в нашей сети, который мы используем для ведения журнала. Приложения используют basicHttpBinding для отправки сообщений журнала и регистрирует их в базе данных. Большая часть журналов из всех других приложений ограничена несколькими десятками журналов за операцию. Недавно мы портировали другое приложение для использования этого сервиса регистрации. Это приложение регистрирует немного более агрессивно, чем любой другой клиент для нашей службы регистрации. У него есть операция, которая за время его работы может регистрировать более 100000 сообщений (это для импорта 100000 записей через файл CSV).
В попытке найти способ сделать это более эффективным, было предложено, чтобы я попробовал MSMQ поставить в очередь запросы журнала и переслать их в службу вместо того, чтобы приложение напрямую связывалось со службой ведения журнала (запрос отправлялся в отдельный поток для целей производительности). Таким образом, приложение не блокируется во время записи журнала. Я реализовал проверку концепции для этого решения MSMQ на своей локальной машине, но так как я никогда не использовал MSMQ раньше, и, поскольку я только сейчас изучаю, каково его место технологически, я обнаружил, что у меня много вопросов и мало ответов, Я надеюсь, что кто-то может указать мне краткую информацию о том, как работает MSMQ, чтобы я мог лучше отладить это доказательство концепции, которое я написал.
Что я вижу после реализации MSMQ:
- Мое приложение, которое отправляет журналы в MSMQ, возвращается почти сразу (а не ожидает фиксации журнала), что я и хочу.
- Несмотря на то, что я отправил 1000 журналов в приложение MSMQ менее чем за 30 секунд, для всех 1000 журналов требуется несколько минут, чтобы попасть в базу данных. Похоже, что в моей очереди включено какое-то регулирование, когда оно задерживает запросы журнала, но я не знаю, как / где это проверить.
- Если я использую net.tcp на сервере, получающем журналы от службы MSMQ, я получаю массу ошибок времени ожидания службы, и только 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 часов исследований через Google. Большинство документов, которые я нашел, довольно старые (2007 г.) и их трудно прочитать. Возможно, они ожидают, что у меня будет некоторый базовый уровень знаний по этому вопросу.
1 ответ
То, что вы видите (если вы используете привязку net.msmq на вашем WCF), это то, что должно произойти.
MSMQ, как средство хранения и пересылки, будет хранить сообщения в очереди на отправляющем клиенте и принимающем сервере до тех пор, пока не станет доступной пропускная способность сети или обработки. Что это делает, так это снимает нагрузку с клиента (как вы заметили), делая процесс асинхронным.
Вы можете просматривать состояния очередей с помощью Performance Monitor, количество сообщений в исходящей очереди (на клиенте) и очереди сервера записываются в счетчики производительности в режиме реального времени и могут просматриваться и / или регистрироваться.
Если производительность ниже оптимальной, вы можете изменить настройки регулирования WCF, чтобы обеспечить более параллельные соединения в поведении вашей службы.
например
<serviceThrottling
maxConcurrentCalls="20"
maxConcurrentSessions="20"
maxConcurrentInstances="20"
/>