воскресенье, 2 ноября 2014 г.

13. ZeroMQ: универсальный решатель проблем или что делать, если сообщения теряются.

(Начало - здесь.)

Потери сообщений.


Сообщения атомарны, это хорошо. То есть, если вы что-то получаете - то получаете это полностью.
Плохо то, что если что-то теряется, то вы не получаете вообще ничего.

Далее - универсальный решатель проблем потерь сообщений.





  • Для сокетов SUB, всегда устанавливать подписку с помощью zmq_setsockopt() и ZMQ_SUBSCRIBE, или не получите ни одного сообщения. Так как вы подписываетесь на сообщения с заданным префиксом, для приема всех сообщений следует указать префикс "" (пустая строка).
  • Если вы стартуете сокет SUB (то есть, соединяетесь с сокетом PUB) после того, как сокет PUB начал рассылать данные, вы потеряете все, что было разослано до вашего подключения. Если это является проблемой, поменяйте архитектуру так, чтобы сокет SUB стартовал первым, а лишь затем начинайте публикацию данных с сокетом PUB.
  • Даже если сокеты SUB и PUB синхронизированы, сообщения могут все равно теряться. Это из-за того, что внутренние очереди могут быть еще не созданы до момента фактического коннекта. Если вы можете переключить направление операций bind/connect так, чтобы для сокета SUB выполнялся bind, а для сокета PUB - connect, возможно, вы получите более рабочий вариант.
  • Если используются сокеты REP и REQ, но при этом не соблюдается синхронный порядок операций запрос/ответ/запрос/ответ, ZeroMQ будет сообщать об ошибках, которые вы, возможно, будете игнорировать. Это также будет выглядеть как потеря сообщений. При использовании сокетов REQ или REP следует строго соблюдать последовательность запросов и ответов на обеих сторонах соединения. И всегда в реальном коде следует проверять коды ошибок после вызовов ZeroMQ.
  • Если используются сокеты PUSH, может получиться, что первые подключившиеся сокеты PULL получат несоразмерно большое количество сообщений. Равномерное распределение сообщений возможно лишь в случае, когда все сокеты PULL успешкно подключились, что может занять несколько миллисекунд. В качестве альтернативы PUSH/PULL, для если нагрузка невелика, следует рассмотреть пару ROUTER/DEALER и шаблон балансировки нагрузки.
  • Разделение сокетов между нитями приведет к неустойчивому поведению и авариям.
  • Если используется транспорт inproc, убедитесь, что оба сокета имеют общий контекст. Иначе будет отказ на стороне коннекта. Также, сначала делайте bind, а лишь затем - connect (Замечание. В ZeroMQ версии 4.* эта проблема решена, bind и connect для inproc может быть выполнен в любой последовательности). Транаспорт inproc не отключаемый, в отличии от tcp.
  • При использовании сокетов ROUTER очень легко потерять сообщения, если случайно отправлены неверные кадры идентификации(или если вообще забыть про кадры идентификации). Отличной идеей будет установка для таких сокетов ROUTER отции ZMQ_ROUTER_MANDATORY, но все равно не следует забывать проверять код завершения после каждого вызова ZMQ.
  • Последнее. Если вы все сделали правильно, но ничего не работает, сделайте крошечное тестовое приложение, воспроизводящее проблему и запросите помощь у сообщества ZeroMQ.

Дальше мы рассмотрим устройство пакетов данных для схемы "Издатель - Подписчик".

Комментариев нет :

Отправить комментарий