У нас есть настройка Spring Cloud Config с использованием серверных частей базы данных Vault (MySQL и RabbitMQ), что дает нам возможность вводить сгенерированные учетные данные в такие свойства, как:
spring.rabbitmq.username
spring.rabbitmq.password
Когда наше приложение запускается, у нас есть новый набор учетных данных Rabbit, и у нас есть возможность запросить новый набор по запросу.
Поскольку наши учетные данные Rabbit управляются Vault извне, срок их действия может истечь/удалить в любое время в течение жизни приложения (это также сценарий проверки устойчивости).
Мой вопрос в том, как мы можем (эффективно, надежно):
- Обнаружение истечения срока действия сгенерированных учетных данных
- Обновите наш существующий Spring AMQP
CachingConnectionFactory
новыми учетными данными.
Мы работаем, исходя из того, что это должно обрабатываться исключительно на стороне клиента в целях обеспечения устойчивости, даже если сервер желает или может отправлять уведомления об истечении срока действия.
С чем мы боремся, так это с тем, как определить истечение срока действия учетных данных, чтобы мы могли затем перенастроить файл CachingConnectionFactory
.
Возможности включают в себя:
- Что у нас есть сейчас:
ChannelListener
, который создает список всех вновь созданныхChannel
и пытается создать/удалить анонимныйQueue
каждые x секунд, прослушивая любыеShutdownSignalException
черезShutdownListener
, которые могут иметь код состояния 403. Кажется, что это работает, но немного сложно, и мы видели проблемы параллелизма, делающие что-то нетривиальное в обработчике выключения. - Как-нибудь подключитесь к
CachingConnectionFactory
. Мы пытались работать с клоном класса, но, помимо сложности этого, мы просто получилиRESOURCE_LOCKED
ошибок, создающих очереди. - Что-то более простое и легкое, например. просто опрашивайте брокера каждые x секунд, чтобы убедиться, что текущие учетные данные все еще существуют.
Частично проблема заключается в том, что ACCESS_REFUSED
— то, что вы получаете, когда CachingConnectionFactory
пытается работать с удаленными учетными данными, — обычно рассматривается как фатальная ошибка неправильной настройки, а не как часть какого-либо реального рабочего процесса, или это может быть восстановлено.
Есть ли здесь изящное решение?
Использование: Spring Boot 1.5.10-RELEASE, Spring Cloud Dalston SR4
Обновление:
На стороне RabbitTemplate
не генерируется никаких исключений — с RetryTemplate
или без него — даже когда CachingConnectionFactory
правильно определяет ACCESS_REFUSED
для обмена, на который я отправляю.
Конфигурация:
spring
rabbitmq:
host: rabbitmq.service.consul
port: 5672
virtualHost: /
template:
retry:
enabled: true
Код:
@Autowired private RabbitTemplate rt; // From RabbitAutoConfiguration
@Bean
public DirectExchange emailExchange() {
return new DirectExchange("email");
}
public void sendEmail() {
this.rt.send("email", "email.send", "test payload");
}
Приложение запускается, объявляя обмен email
. Пользовательский интерфейс RabbitMQ показывает моего (сгенерированного) пользователя и подключение к бирже, что нормально при запуске. Затем я моделирую истечение срока действия учетных данных, вручную удаляя этого пользователя с помощью пользовательского интерфейса, прежде чем запускать локальный тест для вызова электронной почты sendEmail()
выше.
В результате вызова RabbitTemplate
не создаются исключения или не регистрируются ошибки, но регистрируется следующая (ожидаемая) ошибка:
[Соединение AMQP 127.0.0.1:5672] ОШИБКА o.s.a.r.c.CachingConnectionFactory — отключение канала: ошибка канала; метод протокола: #method(reply-code=403, answer-text=ACCESS_REFUSED - доступ к обмену 'электронной почтой' в vhost '/' запрещен для пользователя 'cert-configserver-75c3ae60-da76-3058-e7df-a7b90ef72171', class- идентификатор = 60, идентификатор метода = 40)
Если не считать проверки учетных данных перед всеми вызовами RabbitTemplate.send()
, я хотел бы знать, есть ли способ перехватить ошибку ACCESS_REFUSED
во время отправки, чтобы я мог обновить учетные данные, как я это делаю для слушателей, и дать RetryTemplate
возможность повторить попытку.