Привет всем, я Букай Чен~
Сегодня мы сосредоточимся на наиболее важных проблемах при использовании Spring Event. Это чрезвычайно ценный опыт, полученный после того, как вы столкнулись с подводными камнями в онлайн-производственной среде нашей компании!
Spring Платформа событий реализует механизм публикации и подписки на основе событий. Разработчики могут настраивать события и публиковать события в определенных бизнес-сценариях Spring. Событие будет транслироваться слушателям, слушающим это событие. Слушатели могут реализовать Spring Интерфейс слушателя ApplicationListener
Зарегистрируйтесь,ХОРОШОиспользовать EventListener
аннотация Зарегистрируйтесь。
Это краткое введение в Spring Event. В Интернете много обучающих программ начального уровня. Я не буду здесь вдаваться в подробности и углубляться в текст!
Расширенный веб-сайт Java: https://java-family.cn.
Spring При передаче сообщения Spring будет ApplicationContext
Найти всех слушателей в getBean получать bean Пример. Однако Spring Существует предел————ApplicationContext
Во время завершения работы GetBean не допускается. В противном случае будет сообщено об ошибке.
Эти знания трудно получить. Это причина окончательного позиционирования нашей компании после провала онлайн-среды. На это должен обратить внимание каждый!
Несколько дней назад в онлайн-системе появились два журнала исключений. При получении компонента не удалось найти соответствующий компонент. Стек вызовов меня очень смутил. Почему Get Bean не смог найти соответствующий компонент? .
Информация в стопке объяснил причину。Do not request a bean from a BeanFactory in a destroy method implementation
Компоненты не должны быть получены из контекста, пока контекст приложения закрыт. Как оказалось, эта проблема возникает во время отключения службы.....
Из-за высокого системного трафика и миллионов ежедневных заказов параллельная работа одной машины относительно высока даже в непиковые периоды, поэтому небольшой объем трафика поступает или не обрабатывается в период отключения службы. В этом сценарии, если вы используете Spring Event для публикации событий, Spring не сможет нормально транслировать событие, и обязательно произойдет исключение, приводящее к сбою обработки!
Каждый должен помнить! Перед использованием SpringEvent необходимо сначала управлять службой, чтобы при ее закрытии сначала отсекался входящий трафик (Http, MQ, RPC), а затем закрывалась служба и закрывался контекст Spring!
Подробный анализ см.:
https://juejin.cn/post/7281159113882468371
Ситуация, с которой столкнулась наша компания: Kafka conumser существовать init-method
стадия начинается потребление, однако Spring EventListener быть зарегистрированным в Spring момент времени отстает init-method
момент времени, поэтому Kafka Consumer используется в Spring Event При публикации события прослушиватель не найден, и обработка сообщения теряется.
Как вы можете видеть на картинке ниже init-method
момент времени отстающий EventListener Зарегистрированный момент времени。
Проще говоря: SpringBoot Будет ли Spring полностью запущен до открытия Httpпоток. Это дает нам вдохновение: следует ли существовать Весна После завершения запуска включите входящий трафик.Rpcи MQ-трафик Так и должно быть, поэтому предлагаю всем существовать SmartLifecype
или ContextRefreshedEvent
Позиция ожидания Зарегистрируйтесь на сервисе и включите трафик.
лучшие практика такова: возможность трансформировать систему для открытия входного потока (Http, MQ, RPC) для обеспечения существования Spring После завершения запуска включите входящий трафик.
У каждого хорошего программиста должен быть свой набор инструментов. Он может выбрать наиболее подходящие инструменты для разных бизнес-сценариев.
Для каких бизнес-сценариев подходит SpringEvent? Это определяется особенностями модели подписки-публикации.
Модель публикации-подписки реализует разделение модулей публикации и подписки. Однако для сценариев строгой согласованности модель публикации-подписки не подходит.
Бизнес с сильной последовательностью, такой как сценарий коносамента. На этапе коносамента успешный вычет запасов и коносамент успешного заказа должны быть точно такими же. Такие сценарии, как сбой вычета запасов, но успех коносамента; сбой коносамента и отсутствие отката запасов, являются ненормальными сценариями, которых следует избегать!
Сценарий коносамента, используйте Spring Событие будет иметь много проблем. Предположим, что выпуск предшествует событию перед коносаментом, а бизнес-логика подписчика события может включать такие операции, как списание запасов и блокировка ресурсов купонов. Ошибка вычета запасов. Неспособность заблокировать ресурсы требует отката всего процесса коносамента. Spring Модель подписки на события не может этого обеспечить. Исключение подписки——>откат способность.
Издатель событий не может знать, какие подписки не удалось использовать, а какие подписчики успешно? Процесс отката не может быть запущен точно. (Если вы принудительно откатите на основе события Spring, вы также можете это сделать, но решение будет очень сложным!)
Сценарии окончательной согласованности идеально подходят для использования Spring Events.
Например, после успешного оформления коносамента вы можете использовать SpringEvent для отделения MQ и снятия блокировок и других ресурсов. Почему? Потому что после того, как бизнес убедится в успешности коносамента, коносамент действительно был успешным, и последующие отделочные работы не должны спровоцировать срыв заказа.
Среди подписчиков существующего успешного события,Есть только один результат выполнения — успех. Даже если случился провал,Вам также следует попробовать еще раз, пока не добьетесь успеха. Например выпускать Коносамент успешный MQ Сообщения, освобождение ресурсов, таких как блокировки коносаментов, — все это бизнес-логика, которая должна добиться успеха.
Давайте приведем еще один пример,Наша компания использует фреймворк Spring Event при обработке сообщений о заказах. существуют В этой сцене,Нам нужно обработать завершение выполнения, завершение возврата, истечение срока действия заказа и т. д.,И каждое событие имеет независимую бизнес-логику.,Каждый бизнес-сценарий представляет собой сценарий конечной согласованности. Приведите пример,После завершения исполнения расчетная система должна быть уведомлена о данных исполнения, сумме заказа и других данных. Этот бизнес-сценарий представляет собой сценарий окончательной согласованности.,а не сильная последовательность,Это связано с тем, что даже если урегулирование уведомления не удастся,,Просто попробуй еще раз,Нет необходимости откатывать процесс выполнения.
Если мы не используем Spring Event,Затем мне нужно вручную написать шаблон наблюдателя,И уведомить сообщение о заказе соответствующему наблюдателю в соответствии со статусом. Кроме того, всякий раз, когда добавляется новая бизнес-логика,,Мне нужно добавить группу потребителей Kafka.,И проанализировать сообщение заказа в существующем коде,Затем отправьте событие соответствующим подписчикам в зависимости от статуса. Короче говоря, мне нужно распределить событие соответствующим слушателям согласно статусу.
существуют В этой сцене используйте Spring Мероприятие очень подходящее. Каждое событие может быть инкапсулировано как Spring Event,И любую бизнес-логику можно передать@EventListener
Аннотация для регистрации соответствующего статусасобытиеслушатель(Однако следует отметить, что,Если подписчиков слишком много,Тогда время потребления сообщений Kafka может увеличиться. Так как же это решить? ). использовать Spring Event Фреймворк намного лучше, чем писать собственный рукописный шаблон. прослушивателя.
Spring Событие подходит для бизнес-сценариев, в которых необходимо обеспечить конечную согласованность, но для обеспечения надежности необходимо предоставить возможности повторных попыток. Используя applicationContext.publishEvent(event)
Метод выпускасобытие, Spring будет выполнять связанных подписчиков по порядку. Если возникает исключение, publicEvent Метод выдаст исключение, и пользователь почувствует, что обработка логики подписки не удалась.
существоватьвыпускатьсобытиечас,Необходимо учитывать ситуацию, когда логика подписки ненормальна.,Я предлагаю три решения
Логика подписки может повторить попытку, чтобы гарантировать успех. Например, использование аннотации повтора Spring может гарантировать повторное выполнение метода при возникновении исключения.
Следующий пример кода performSuccess
Когда метод генерирует исключение, Spring Метод будет выполняться повторно до успешного завершения, вплоть до повторной попытки. 3 раз, можно установить время интервала и время приращения интервала повторных попыток.
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 100L, multiplier = 2))
public void performSuccess(PerformEvent event) {
}
использовать @Retryable Прежде чем комментировать, не забудьте представить spring-retry
pom полагаться
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
еслисуществовать Kafka потребительиспользуется вSpring Событие, обработка повторных попыток очень проста. Вам нужно обращаться к нам только в том случае, если ваше потребление является ненормальным. Kafka Просто верните провал потребления, Кафка Попытка будет повторена автоматически.
также,Сообщения также можно отправлять в специальную очередь недоставленных писем.,существуют повторные обработки сообщений в очереди недоставленных писем! разные компании Kafka Схема реализации возможности повтора может быть разной, и каждый может сделать свой выбор.
Процесс устранения неполадок
Если запрос не может быть повторен больше максимального количества попыток, бизнес-система сообщит об ошибке. MQ, потребление платформы управления отказами MQ,Соберите неисправности и закиньте их в библиотеку. Студенты, занимающиеся исследованиями и разработками, получают уведомление о неисправности,Вмешайтесь для устранения проблем. В то же время студенты, занимающиеся исследованиями и разработками, могут видеть список и подробную информацию о неисправностях в фоновом режиме управления неисправностями.
Выяснив причину проблемы и попросив соответствующих коллег устранить проблему, нажмите кнопку «Повторить». Когда фоновая система управления сбоями получает запрос на повторную попытку, она вызывает бизнес-систему через Rpc SPI, чтобы повторить ошибку и уведомлять фоновую систему управления о результатах успеха и неудачи.
Для повышения надежности необходимы дополнительные механизмы повторных попыток, обеспечивающие Spring подпискавыпускатьнадежность。
Если есть повторные попытки, должна быть идемпотентность! Убедитесь, что логика подписчика идемпотентна. Spring не знает, какие подписчики выполнили операцию успешно, а какие нет. Spring выполнит всех подписчиков при следующей повторной попытке. Следовательно, логика подписки должна быть идемпотентной, чтобы предотвратить возникновение несогласованности данных.
Однажды мой друг сказал мне, что наша компания хороша в Spring Event Сценарий приложения следует заменить на MQ。существовать Позвольте мне объяснить это
Spring Событие и MQ Однако все они относятся к подписке на выпуск приложения. MQ Сравнивать SpringEvent Мощный и сложный. МК Больше подходит для развязки, изоляции и уведомления о событиях между приложениями. Например, такие события, как оплата заказа, завершение заказа, завершение выполнения заказа и т. д., должны транслироваться для уведомления других последующих микросервисов. Этот сценарий больше подходит для использования MQ 。
Однако для сценариев, когда вам нужно подписаться на выпуск внутри приложения, лучше использовать Весеннее событие. Эти два понятия не противоречат друг другу, MQ Возможности сильнее, а технические решения более «тяжелые». Весна Event Более компактный и подходит для подписок внутри приложения, чтобы обеспечить разделение бизнес-логики.