zeromq, C++, нужно ли устанавливать максимальную отметку для подписчиков?

Я быстро протестировал ZeroMQ PUB/SUB, и теперь у меня есть рабочий код. Тем не менее, я немного смущен концепцией высокой отметки, применяемой в zeromq.

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

Однако также возможно установить HWM на принимающем сокете абонента. Есть ли причина устанавливать HWM на стороне подписчика и чем это будет отличаться от установки HWM издателя?


person user788171    schedule 26.04.2013    source источник


Ответы (2)


Краткий ответ:

В издателе мы почти всегда должны тщательно учитывать HWM, потому что существует множество причин сбоя (нехватки памяти), влияющих на систему в целом (поскольку издатель обслуживает всех подписчиков).

Также в подписчике бывают случаи, когда регулирование HWM может быть полезным, но это зависит главным образом от характера подписчика, того, что он делает с полученным сообщением, и насколько высока вероятность того, что он не мог вовремя обработать большое количество полученных сообщений; и ожидаемой средой выполнения (сколько памяти доступно, количество подписчиков и т.д.)

Более подробный ответ:

ZMQ использует концепцию HWM (высокая отметка) для определения пропускной способности внутренних труб. Каждое соединение из сокета или в сокет имеет свой канал и HWM для отправки и/или получения, в зависимости от типа сокета. Некоторые сокеты ( PUB, PUSH ) имеют только буферы отправки. Некоторые ( SUB, PULL, REQ, REP ) имеют только буферы приема. Некоторые ( DEALER, ROUTER, PAIR ) имеют буферы отправки и приема.

Доступные параметры сокета:

ZMQ 3.0+ накладывает ограничения по умолчанию на свои внутренние буферы (так называемые HWM), потому что HWM — это отличный способ уменьшить проблемы с переполнением памяти.

И ZMQ_PUB, и ZMQ_SUB имеют параметр ZMQ_HWM, для которого установлено значение «Отбросить», поэтому, когда лимиты увеличиваются, память подписчика или издателя должна перестать расти, по крайней мере, на то, что зависит от буферов ZMQ.

Обычно больше всего в защите от неразборчивого использования памяти (проблем нехватки памяти) нуждаются издатели:

Во внутрипроцессном транспорте отправитель и получатель совместно используют одни и те же буферы, поэтому реальный HWM представляет собой сумму HWM, установленных обеими сторонами.

Но если вы используете TCP и подписчик работает медленно, сообщения будут стоять в очереди на издателе.

Общие причины отказа PUB-SUB включают в себя:

  • Подписчики могут получать сообщения слишком медленно, поэтому очереди накапливаются, а затем переполняются.
  • Сети могут стать слишком медленными, поэтому очереди на стороне издателя переполняются, и издатели аварийно завершают работу.

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

С точки зрения издателя, отличная стратегия, которую мы используем при правильной настройке ZWM, заключается в прекращении очереди новых сообщений через некоторое время, новые сообщения просто отклоняются или удаляются; это то, что делает ØMQ, когда издатель устанавливает HWM.

ZMQ также может ставить сообщения в очередь на подписчике.

Если у кого-то закончится память и произойдет сбой, то это будет подписчик, а не издатель, что справедливо. Это идеально подходит для «пиковых» потоков, когда подписчик какое-то время не успевает, но может наверстать упущенное, когда поток замедляется.

Примечание: HWM неточны; в то время как вы можете получить до 1000 сообщений по умолчанию, реальный размер буфера может быть намного меньше (всего половина) из-за того, как libzmq реализует свои очереди.

Основным источником этих предположений является книга Питера Хинтдженса Code Connected Volume 1, доступная онлайн в электронном формате; в нем есть глава, посвященная максимальным значениям и содержащая дополнительные пояснения по этой теме.

person Franco Rondini    schedule 08.05.2013
comment
Привет, Франко, спасибо за ваш ответ, это помогает частично ответить на вопрос, но с точки зрения реализации это все еще немного неясно. Похоже, мне нужен HWM для подписчика и издателя, чтобы избежать сбоев с обеих сторон, поэтому я бы использовал ZMQ_DEALER. Нужно ли явно устанавливать ZMQ_SNDHWM и ZMQ_RCVHWM как в client.cpp, так и в server.cpp? Или достаточно только установить ZMQ_SNDHWM на server.cpp и ZMQ_RCVHWM на client.cpp? - person user788171; 08.05.2013
comment
FДостаточно установить ZMQ_SNDHWM для сокета, который вы используете для отправки сообщений, и ZMQ_RCVHWM для сокета, который их получает. Если вы используете разные шаблоны, прочитайте api.zeromq.org/3-0%3azmq. -socket и обратите внимание на действие параметра ZMQ_HWM, поскольку оно зависит от типа сокета. - person Franco Rondini; 08.05.2013
comment
@FrancoRondini, спасибо за этот подробный ответ, он мне очень помог. - person Matt; 11.06.2013

Было бы полезно установить ZMQ_SNDHWM на подписчике, если вы подписаны сразу более чем на 1000 тем (насколько мне известно, по умолчанию ZMQ_SNDHWM равно 1000). Итак, если вы подпишитесь следующим образом:

for(i = 0; i < 2000; i++)
{
    subscriber.setsockopt( ZMQ_SUBSCRIBE, &i, sizeof(i));
}

Это не сработает из-за переполнения очереди вывода.

Но если вы установите перед подключением

subscriber.setsockopt( ZMQ_RCVHWM, &i, sizeof(i));
subscriber.setsockopt( ZMQ_SNDHWM, &i, sizeof(i));

Это работает хорошо.

person Danil    schedule 20.09.2013
comment
При чем тут количество тем? Наверняка это зависит от скорости передачи данных? - person easytiger; 30.04.2014
comment
Ну... Я хотел подписаться на все темы в самом начале, а их у меня было более 1000. Так что это было проблемой, потому что на самом деле подписка могла произойти еще до того, как пиры будут подключены. Возможно, если делать это шаг за шагом, скажем, с некоторой задержкой, это могло бы сработать. - person Danil; 24.06.2014