Подтвердить что ты не робот

Почему MSMQ быстрее, чем WCF QueueService?

У меня есть собственная служба WCF на консоли с привязкой netNamedPipeBinding. Служба имеет только один пустой метод Send(DataTable bulk)

[ServiceContract]
public interface IWcfQueueService
{
    [OperationContract]
    void Send(DataTable bulk);       
}
public class WcfQueueService : IWcfQueueService
{
    public void Send(DataTable bulk)
    {           
       // Here would be something like _bulks.Add(bulk);
       // BUT, for now it is empty method and still it slower than MSMQ
    }    
}

Мой клиент получает 200-килобайтные входы от БД и обрабатывает его с помощью нашего BoundedThreadPool (только создает, допустим, 20 потоков). Каждый вход обрабатывается с помощью другого потока. Каждый поток выполняет MyMethod, а в конце MyMethod результат добавляется к bulkManager.

public void MyMethod(string input)
{            
    var res = ProcessInput(input);
    bulkManager.Add(res);
}

Когда bulkManager накапливает N элементов (= объем), он передает основную часть другому потоку, все, что он делает, представляет собой очередь, которая содержит один из двух методов:

  • Если wcf включен: wcfQueueService.Send(bulk);
  • else, если включен MSMQ: new MessageQueue(@".\private$\q").Send(new Message {Body = bulk});

Все два метода работают, но MSMQ работает намного быстрее. С клиентом MSMQ удается обрабатывать около 80 тыс. Штук в 20секундах, а с wcf всего 20 КБ-30 тыс. Штук. Я не понимаю, почему это происходит. Мой WCF работает в разных процессах, таких как MSMQ. Кроме того, мой WCF ничего не хранит, у него есть пустой метод. Итак, почему MSMQ выигрывает WCF?

Обновление

Как leppie предложил попробовать .NetRemoting. NetRemoting действительно улучшил скорость. Клиент обработал 60K. Но,

  • Он все еще медленнее, чем MSMQ
  • Как я читал .Net Remoting устарел WCF, а WCF должен быть быстрее, чем .Net Remoting в соответствии с this, так почему я получаю что мой wcf медленнее? Может быть, моя привязка неверна?
4b9b3361

Ответ 1

Вы не сравнитесь с подобными.

Самое очевидное различие заключается в том, что в случае WCF ваши тайминги включают выполнение всего стека каналов служебной стороны и вызов операции, тогда как ваш прямой случай MSMQ измеряет время для размещения полезной нагрузки на стороне клиента. Имейте в виду, что обработка служебной стороны в WCF включает десериализацию вашего объекта DataTable, что, вероятно, довольно дорого, если ваш фактор увеличения N велико.

Более того, в зависимости от того, как вы настроили ручку настройки обслуживания и дросселирования, запросы от клиента могут выполняться быстрее, чем служба настроена для обработки, в результате чего сами запросы ставятся в очередь для выполнения на сервисная сторона.

Кроме того, в зависимости от того, как вы настроили привязку, могут быть и другие существенные различия, например, безопасность. Кстати, действительно ли вы использовали NetNamedPipeBinding (как заявляет ваш вопрос), а не NetMsmqBinding, поскольку название, казалось, подразумевало? Если это так, используя конфигурацию привязки по умолчанию, у вас будет полностью ненужное шифрование и подписание каждого массового сообщения, которое не происходит в вашем прямом MSMQ. Эти криптографические операции с большими сообщениями также будут относительно дорогими.

Лучшее сравнение было бы с работой WCF, определенной как OneWay.

Ответ 2

Можете ли вы предоставить пример кода, который показывает поведение, которое вы видите?

Я провел собственное тестирование, создав 20 000 сообщений для отправки. Я попробовал оба, 20 000 с прямым MSMQ и 20 000 с WCF, абстрагирующими конечную точку MSMQ для меня.

20 000 с прямым MSMQ использовали 64,75% процессорного времени, а версия WCF, отправляющая 20 000 сообщений, использовала 34,16% времени процессора (с использованием функции анализа в Visual Studio Ultimate).

Если бы я не сделал ошибку на моем конце, версия WCF была почти в два раза быстрее, чем эквивалент MSMQ с жесткой кодировкой.

Ответ 3

Я думаю, что разница в том, что происходит в вашей работе WCF, чем то, что MSMQ делает, когда оно принимает запрос.

Я ожидаю, что метод, который выполняется, когда вы вставляете сообщение с MSMQ simple, принимает сообщение и ничего больше. Некоторые работники делают тяжелый подъем.

В вашей операции вам необходимо передать запрос одному экземпляру обработчика запросов. Экземпляр обработчика запроса должен быть создан, когда служба "развернута".

Вы также можете найти улучшенную производительность, используя параллельную библиотеку задач в .NET 4, чтобы распараллелить ваши запросы.