Проблема с настройкой возможности повторной попытки с помощью Spring AMQP с использованием шаблона повторной попытки

Я пытаюсь настроить возможность повторной попытки в своем проекте Spring Integration, где я пытаюсь подключиться к серверам Rabbit, следуя подробностям, представленным здесь в этом статья раздел 3.3.1. Но похоже, что политика повторных попыток не срабатывает. Вот что у меня есть в моей конфигурации:

<!-- Spring AMQP Template -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"   retry-template="retryTemplate"
    exchange="myExchange" />

<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
    <property name="backOffPolicy">
        <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
            <property name="initialInterval" value="8" />
            <property name="multiplier" value="100.0" />
            <property name="maxInterval" value="100000" />
        </bean>
    </property>
    <property name="retryPolicy">
        <bean class="org.springframework.retry.policy.SimpleRetryPolicy">
            <property name="maxAttempts" value="3"/>
        </bean>
    </property>         
</bean>
<!-- Spring AMQP Admin -->
<rabbit:admin connection-factory="connectionFactory" />

Основываясь на фрагменте, я ожидаю, что повторная попытка произойдет 3 раза с экспоненциальным интервалом. Но, основываясь на журналах, я вижу, что повторная попытка предпринимается с интервалом в 7 секунд, и она продолжается вечно (не останавливается после 3 раз).

Интересно, может ли кто-нибудь указать, что не так в моей конфигурации.


person ignatan    schedule 31.03.2015    source источник
comment
привет, игнатан.. я тоже столкнулся с той же проблемой, не могли бы вы поделиться решением, пожалуйста... #спасибо   -  person Sujeeth Damodharan    schedule 26.08.2015


Ответы (1)


Во-первых, maxattempts=3 означает 3 попытки (2 попытки), поэтому вы должны увидеть первоначальную попытку, вторую попытку через 8 мс, а затем последнюю попытку через 800 мс.

Множитель 100 кажется чрезмерным - следующая попытка (если maxattempts равно 4) будет через 80 секунд.

Я предлагаю вам включить ведение журнала DEBUG, чтобы следить за ходом повторных попыток.

person Gary Russell    schedule 31.03.2015
comment
Спасибо за ваш ответ. Когда я включил ведение журнала, я вижу, что используется DEFAULT_RECOVERY_INTERVAL SimpleMessageListenerContainer. Из журналов: 09:01:52,077 DEBUG [org.springframework.amqp.rabbit.listener.BlockingQueueConsumer] (SimpleAsyncTaskExecutor-4 ) Запуск потребителя-потребителя: tags=[{}], channel=null, acceptMode=AUTO local queue size=0 09:01:53,079 DEBUG [org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer] (SimpleAsyncTaskExecutor-4) Восстановление потребителя за 5000 мс. Итак, это было 5 секунд, а не 7, но интересно, почему RetryPolicy не срабатывает - person ignatan; 31.03.2015
comment
Нет; вы неправильно понимаете повторную попытку в RabbitTemplate - повторная попытка там не зависит от контейнера прослушивателя сообщений - конечно, если есть проблема с подключением, это повлияет на оба. Сообщение поступает в контейнер; предположительно вы вызываете шаблон в потоке контейнера. Будут предприняты повторные попытки; при исчерпании исключение будет возвращено в контейнер. Вам нужно предоставить гораздо больше информации о вашем приложении, если вам нужна помощь. Если вы не можете понять это из журналов, опубликуйте их где-нибудь (или в Gist, если они слишком велики) вместе с полной конфигурацией. - person Gary Russell; 31.03.2015
comment
Интересно, неправильно ли я пытаюсь использовать RetryTemplate. Мое приложение выбирает сообщения из rabbitMQ (сервер A), преобразует данные и затем помещает их в другой rabbitMQ (сервер B). Что я понял, так это то, что если я отключу ServerB, повторная попытка сработает .... Я вижу, что попытки выполняются на основе retryPolicy, и выдает исключение после того, как попытки исчерпаны. Теперь, когда я отключаю ServerA, я вижу повторные попытки подключения к серверу A контейнером прослушивателя с интервалом в 5 секунд. Есть ли способ применить повторную политику на уровне контейнера прослушивателя? - person ignatan; 31.03.2015
comment
Добавьте цепочку рекомендаций в контейнер прослушивателя с помощью ссылки рекомендация о повторных попытках с отслеживанием состояния — требует, чтобы отправитель предоставил заголовок messageId для управления состоянием повторных попыток. Совет без сохранения состояния будет повторять попытку внутри контейнера без возврата обратно в контейнер (до тех пор, пока попытки не будут исчерпаны и не будет восстановлено). - person Gary Russell; 31.03.2015
comment
Спасибо за ссылку Гэри. Из статьи: Если сбой вызван разрывом соединения (не бизнес-исключением), то потребитель, который собирает сообщения для прослушивателя, должен быть отменен и перезапущен. SimpleMessageListenerContainer бесконечно зацикливается, пытаясь перезапустить потребителя... Один побочный эффект заключается в том, что если брокер не работает при запуске контейнера, он просто будет продолжать попытки, пока не будет установлено соединение. Интересно, есть ли способ применить политику повторной попытки, чтобы мы могли контролировать перезапуск контейнера... - person ignatan; 01.04.2015
comment
Нет; повторное подключение к брокеру, когда он не работает, выполняется непрерывно и повторяется в соответствии с recoveryInterval. Использование экспоненциальной повторной попытки (и, в конечном итоге, отказ от нее) не имеет большого смысла для этого сценария — как контейнер вообще узнает, что брокер вернулся? Если вы действительно хотите это сделать, вы можете использовать какой-нибудь внешний монитор, чтобы продолжить попытки получить соединение с фабрики и через некоторое время вызвать stop() в контейнере прослушивателя. А затем, предположительно, через некоторое время позвонить start(). - person Gary Russell; 01.04.2015
comment
Спасибо, Гэри. Это имеет смысл - person ignatan; 02.04.2015