Bus.Send блокируется при использовании Azure Queue с NServiceBus

Я тестирую NServiceBus с серверной частью Azure Queue. Я настроил NServiceBus, используя все настройки по умолчанию, и у меня есть этот код для отправки сообщения:

while ((data = Console.ReadLine()) != null)
{
   Stopwatch sw = new Stopwatch();
   sw.Start();
   Bus.Send("testqueue", new Message() {Data = data});
   sw.Stop();
   Console.WriteLine("Sent time: " + sw.ElapsedMilliseconds);
}

При работе на моей машине разработки для отправки сообщения в очередь требуется ~ 700 мс. Очередь далеко, ~350 мс при записи напрямую с помощью клиента службы хранилища Azure.

Теперь у меня два вопроса:

  1. Я не хочу, чтобы поток блокировался при вызове Bus.Send. Один из вариантов — использовать шаблон async\await. Другой вариант — иметь очередь в памяти для доставки сообщений, аналогично 0MQ. Последний вариант, конечно, не гарантирует доставки, но если есть некоторые возможности мониторинга, я могу с этим смириться.
  2. Почему отправка сообщения занимает в два раза больше времени, чем простая запись в очередь? Можно ли это оптимизировать?

person Alon Catz    schedule 07.07.2014    source источник


Ответы (1)


Каков размер свойства данных?

Я только что провел этот тест сам (используя строку «Что угодно» в качестве данных), и я вижу среднюю задержку ~ 50 мс для каждой удаленной отправки с дросселем каждые 15 секунд, что делает вызовы в этот момент около ~ 300 мс (это ожидается ).

Обратите внимание, что лазурное хранилище является удаленной службой на основе http и, следовательно, подвержено задержке из-за расстояния. Насколько мне известно, здесь также нет опубликованных целевых показателей производительности. Кроме того, у него есть активное регулирование, чтобы отталкивать, когда данные перемещаются, что происходит примерно каждые 15 секунд (см. мой разговор о внутренних устройствах хранилища, чтобы понять, что происходит за кулисами. http://www.slideshare.net/YvesGoeleven/azure-storage-deep-dive)

По теме async/await. Если ваша цель состоит в том, чтобы разблокировать поток пользовательского интерфейса, сделайте это следующим образом...

await Task.Factory.StartNew(() => _bus.Send(new Message{
       Whatever = data
})).ConfigureAwait(false);

Если вашей целью является достижение более высокой пропускной способности, вам следует вместо этого использовать больше отправляющих потоков, поскольку поток в любом случае должен ожидать ответа http, который является либо отправляющим потоком, либо фоновым потоком, запущенным из async/await. Однако обратите внимание, что каждая очередь также регулируется индивидуально (на несколько сотен сообщений в секунду), независимо от того, сколько отправок угроз вы используете.

PS: ИТ-специалистам также рекомендуется изменить следующие настройки в диспетчере точек обслуживания .net, чтобы оптимизировать его для множества небольших HTTP-запросов.

ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = 48;

Надеюсь это поможет...

person Yves Goeleven    schedule 09.07.2014
comment
Спасибо за ваш ответ. Проблема не в длительных задержках. Ожидается 300 мс от моей машины разработчика. Проблема в том, что нет опции async\await и поток должен быть заблокирован во время отправки сообщения. Мы рассчитываем обслуживать 1000 запросов в секунду на одной машине. Если мы пойдем по этому пути, у нас будет как минимум 1000 потоков, которые просто вращаются и ждут ответов от NServiceBus. Когда вы выполняете async\await, поток освобождается на время ожидания. В противном случае поток просто сидит в состоянии ожидания и блокируется. - person Alon Catz; 10.07.2014
comment
Это находится на радаре команд, чтобы обеспечить это, но сейчас я предлагаю вам использовать несколько потоков отправки, например, обернув ваши отправки в параллель. - person Yves Goeleven; 10.07.2014
comment
И используйте несколько очередей, кстати, вы не сможете последовательно заполнять тысячи сообщений через одну очередь, независимо от того, сколько потоков вы используете. - person Yves Goeleven; 10.07.2014