#activemq #activemq-cpp
#activemq #activemq-cpp
Вопрос:
Настройка потребителя CMS с помощью слушателя включает в себя два отдельных вызова: во-первых, получение потребителя:
cms::MessageConsumer* cms::Session::createConsumer( const cms::Destination* );
и затем, установив прослушиватель на потребителе:
void cms::MessageConsumer::setMessageListener( cms::MessageListener* );
Могут ли сообщения быть потеряны, если реализация подписывается на адресата (и получает сообщения от брокера / маршрутизатора) до активации прослушивателя? Или такие сообщения помещаются в очередь внутри и доставляются слушателю при активации?
Почему нет вызова API для создания потребителя с слушателем в качестве конструктивного аргумента? (Это потому, что в спецификации JMS его нет?)
(Дополнение: это, вероятно, недостаток в самом API. Более логичным порядком было бы создать экземпляр потребителя из сеанса и иметь cms::Consumer::subscribe( cms::Destination*, cms::MessageListener* )
метод в API.)
Комментарии:
1.
SimpleAsyncConsumer
Пример в дистрибутиве activemq-cpp — это шоу ужасов, классика плохого подражателя C . Это похоже на работу Java-программиста, пытающегося написать C .2. Если ActiveMQ CMS не удовлетворяет вашим потребностям, всегда есть клиенты C , которые говорят на AMQP. Кроме того, клиенты C STOMP. ActiveMQ поддерживает оба этих протокола.
3. Чем меньше сказано о клиенте Qpid Proton C , тем лучше. (Кодовая база выглядит более разумной, но API, основанный на каком-то дурацком шаблоне проектирования «proactor», с Марса; и AMQP 1.0, похоже, не очень подходит для pub / sub) Тем не менее, я все еще получаю полезную информацию от CMS. Возможно, острые края не являются непреодолимыми.
4. Я также не прочь взломать исходный код, если это необходимо. Есть некоторые довольно очевидные проблемы, например, разработчики забыли — или не знали — что C поддерживает ковариантные возвращаемые типы, поэтому вы обнаруживаете Java-измы, такие как
ActiveMQConnectionFactory::createConnection()
возврат acms::Connection*
, безвозмездная потеря типа подкласса, который затем потребуетсяdynamic_cast
для восстановления в клиентском коде … вздох5. Это с открытым исходным кодом. Я уверен, что вклад будет приветствоваться. Кроме того, я полагаю, что разрабатывается новый клиент Qpid C . См . qpid.2158936.n2.nabble.com /… для обсуждения.
Ответ №1:
Я не думаю, что API обязательно испорчен. Очевидно, что это могло быть разработано по-другому, но я считаю, что решение вашей предполагаемой проблемы исходит от start
метода Connection
объекта (унаследованного через Startable
). Документация для Connection
состояний:
Клиент CMS обычно создает соединение, один или несколько сеансов и несколько производителей и потребителей сообщений. Когда соединение создается, оно находится в режиме остановки. Это означает, что сообщения не доставляются.
Обычно соединение остается в остановленном режиме до завершения настройки (то есть до тех пор, пока не будут созданы все потребители сообщений). В этот момент клиент вызывает метод запуска соединения, и сообщения начинают поступать потребителям соединения. Это соглашение о настройке сводит к минимуму любую путаницу с клиентом, которая может возникнуть в результате асинхронной доставки сообщений, пока клиент все еще находится в процессе настройки.
Соединение может быть запущено немедленно, а настройка может быть выполнена впоследствии. Клиенты, которые делают это, должны быть готовы обрабатывать асинхронную доставку сообщений, пока они все еще находятся в процессе настройки.
Это тот же шаблон, которому следует JMS.
В любом случае я не думаю, что существует какой-либо риск потери сообщений независимо от того, когда вы вызываете start()
. Если потребитель использует режим автоматического подтверждения, то сообщения должны автоматически подтверждаться только после того, как они доставлены синхронно с помощью одного из методов приема или асинхронно через прослушиватель onMessage
. По моей оценке, поступить иначе было бы ошибкой. Я работал с JMS в течение последних 10 лет над различными реализациями, и я никогда не видел какого-либо состояния, при котором сообщения были потеряны, связанные с этим.
Если вы хотите добавить потребителей после того, как вы уже вызвали start()
, вы, конечно, можете stop()
сначала позвонить, но я не вижу никаких проблем с простым добавлением их на лету.
Комментарии:
1. ну, да, это работает для подписок, настроенных перед
start()
вызовом. Что, если я захочу добавить еще одну подписку позже, послеstart()
вызова? Должен ли я позвонитьstop()
, настроить нового потребителя, а затемstart()
снова позвонить?2. Я все еще думаю, что это недостаток API. Обычная процедура (в большинстве систем обмена сообщениями) заключается в настройке слушателя / получателя перед регистрацией подписки, именно для того, чтобы избежать условий гонки. (Та же логика применяется к сценариям запроса / ответа, кстати — настройка обработчика ответа перед отправкой запроса.)
3. Спасибо! Я понимаю вашу точку зрения о JMS, но мое внимание было сосредоточено на CMS, предположительно «clone» API. База кода, мягко говоря, не внушает доверия, поэтому мне все еще интересно узнать об опыте работы с клиентской библиотекой C .
4. Кроме того, для чего это стоит, если запрос / ответ в JMS использует семантику «точка-точка» (т. Е. Очередь), Тогда нет строгой необходимости настраивать обработчик ответа перед отправкой запроса.
5. Хороший момент. Я сосредоточился на pub / подсистемах (темы).