Лидер / Последователь против рабочей очереди - PullRequest
10 голосов
/ 14 ноября 2011

Я только что прочитал статью о шаблоне Лидер / Подписчик , и если я правильно понял, я оставляю своих работников в очереди, а первый работник принимает входящий запрос и отсоединяется от очереди.

С обычной рабочей очередью (например, rabbitmq и beanstalkd ) все наоборот: я сохраняю свою работу в очереди, и как только работник заканчивает обработкуон просто берет первую работу из очереди.

Есть что-то, чего мне не хватает?

Итак, каковы преимущества, которые я должен использовать, используя подход Лидер / Последователь вместо рабочей очереди?Или наоборот, в каких ситуациях рабочая очередь подходит лучше?

Пока, Нико

Ответы [ 2 ]

8 голосов
/ 14 ноября 2011

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

Имейте в виду, что в этой статье обсуждаются низкоуровневые механизмы ожидания работы, которые не (легко) поддерживают несколько потоков, ожидающих одну и ту же «очередь» работы.Конструкции более высокого уровня, такие как очереди сообщений, которые поддерживают несколько рабочих потоков, все из которых выполняют блокирующее чтение в одном и том же источнике (конкурирующие потребители AKA), могут не получить описанного преимущества.Более высокий уровень абстракции обеспечивает большую простоту программирования, но, как правило, за счет производительности, которая может быть достигнута при более низкоуровневом подходе.

EDIT1:

Вот подготовленный образец (только псевдокод).Обратите внимание, что я не писал статью и не проверял ее, поэтому я не могу по-настоящему говорить о производительности одного против другого.Но, надеюсь, это показывает разницу в стиле.

// in QueueHandler processing loop

while(true)
{
   // read, blocking until one arrives
   Request req = requestQueue.BlockingRead();

   // we have a unit of work now but the QueueHandler should not process it
   //  because if it is long running then no new requests can be handled.
   //  so we spawn / dispatch to a thread
   ThreadPool.QueueWorkItem(req);
   // or new Thread(DoWork(), req).Start;

   // at this point we know that the request will get picked up in 
   // an unknown but hopefully very short amount of time by a 
   // waiting (sleeping/blocking) or new thread and it will get passed the 
   // work.  But doing so required the use of thread synchronization 
   // primitives that can cause all processors to flush their caches 
   // and other expensive stuff.


} // now loop back up to read the next request

VS

// in Leader

while(true)
{

   // I'm the leader, blocking read until a request arrives
   Request req = queue.BlockingRead();

   // We have a unit of work and we are going to process it ourselves.  
   // But first we notify a follower.
   Followers.PromoteOne();

   // work on the request in this thread!
   DoWorkOn(req);

   // now that I'm done, wait to the the leader
   Followers.BlockingWaitToBeLeader();

}
0 голосов
/ 13 января 2015

Прежде всего, с рабочими очередями вам нужны блокировки на рабочие очереди. Во-вторых, и это главная проблема, с рабочими очередями вы должны разбудить рабочий поток, и этот поток не будет обрабатывать работу, пока планировщик системных задач фактически не выполнит задачу. Что еще хуже, когда вы обрабатываете рабочий элемент с другим ядром процессора, чем то, которое заполняет очередь. Таким образом, вы можете добиться гораздо меньших задержек с помощью шаблона лидера-последователя.

...