Последнее обновление блога год назад, всех заранее с Новым годом (и Днем святого Валентина)!
Введите тему ниже. Spring Cloud Bus соединяет узлы распределенных систем с облегченными брокерами сообщений. Это можно использовать для передачи состояния таблицы (например, изменений конфигурации) или других связанных команд. Ключевая идея заключается в том, что шина похожа на распределенный привод для расширений приложений Spring Boot, но ее также можно использовать в качестве канала связи между приложениями. Spring Cloud предоставляет брокеров для транспорта AMQP и стартеров Kafka, а в будущем также планируется поддержка других транспортных компонентов с тем же базовым набором функций.
Spring Cloud Bus
Spring Cloud Bus
вSpring Cloud Stream
На основе инкапсуляции публикация и подписка на сообщения по заданной теме осуществляется черезSpring Cloud Stream
Конкретная реализация связующего. Таким образом, введенная зависимость может бытьspring-cloud-starter-bus-amqp
иspring-cloud-starter-bus-kafka
Один из них соответствует двум реализациям связующего. Согласно основному приложению из предыдущего раздела, мы заключаем, чтоSpring Cloud Bus
Основные функции следующие:
- на указанную тему
springCloudBus
Подписка на новости и публикация. - Мониторинг событий, включая события обновления, события изменения среды, события подтверждения удаленных приложений и события, отправленные локальным сервером.
В дальнейшем мы возьмем эти два аспекта в качестве основной линии,Spring Cloud Bus
анализ исходного кода. Эта статья в основном публикуется для подписчиков событий.
Подписка и публикация событий
модель, управляемая событиями
Эта часть требует, чтобы читатель сначала понял управляемую событиями модель Spring. Мы кратко познакомим вас с основными концепциями дизайна, чтобы помочь вам легко понять следующее содержание.
модель, управляемая событиями
Модель Spring, управляемая событиями, состоит из трех частей:
- Событие: ApplicationEvent, унаследованное от EventObject JDK, все события будут наследоваться от него и получать источник события через источник.
- Издатель событий: интерфейс ApplicationEventPublisher и ApplicationEventMulticaster, используя этот интерфейс, наш Сервис имеет возможность публиковать события.
- Подписчик событий: ApplicationListener, унаследованный от EventListener JDK, его наследуют все слушатели.
Определение события
Определения событий управляемой событиями модели Spring унаследованы отApplicationEvent
,Spring Cloud Bus
Существует несколько классов событий, каждый из которых наследует важный абстрактный класс.RemoteApplicationEvent
, давайте взглянем на диаграмму классов класса события:
Определение различных событий
Участвующие классы событий: события, которые представляют собой подтверждение определенного событияAckRemoteApplicationEvent
, события изменения средыEnvironmentChangeRemoteApplicationEvent
, обновить событиеRefreshRemoteApplicationEvent
, отправить событиеSentApplicationEvent
, и неизвестные событияUnknownRemoteApplicationEvent
. Рассмотрим определения этих событий отдельно.
Абстрактный базовый класс: RemoteApplicationEvent
Из приведенной выше диаграммы классов мы знаемRemoteApplicationEvent
Это базовый класс других классов событий, определяющий общедоступные свойства объектов событий.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") //序列化时使用子类的名称作为type
@JsonIgnoreProperties("source") //序列化时,忽略 source
public abstract class RemoteApplicationEvent extends ApplicationEvent {
private static final Object TRANSIENT_SOURCE = new Object();
private final String originService;
private final String destinationService;
private final String id;
protected RemoteApplicationEvent(Object source, String originService,
String destinationService) {
super(source);
this.originService = originService;
if (destinationService == null) {
destinationService = "**";
}
if (!"**".equals(destinationService)) {
if (StringUtils.countOccurrencesOf(destinationService, ":") <= 1
&& !StringUtils.endsWithIgnoreCase(destinationService, ":**")) {
//destination的所有实例
destinationService = destinationService + ":**";
}
}
this.destinationService = destinationService;
this.id = UUID.randomUUID().toString();
}
...
}
существуетRemoteApplicationEvent
Три основных общих атрибута: служба источника события, служба назначения, служба назначения и случайно сгенерированный глобальный идентификатор определены в . В методе построения targetService может использовать подстановочный знак {serviceId}:{appContextId}. Если обе переменные опущены, все экземпляры всех служб будут уведомлены. Когда опущен только appContextId, соответствующая служба назначения — это все экземпляры соответствующего идентификатора службы. Кроме того, обратите внимание@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
В соответствии с сериализацией используйте имя подкласса в качестве типа; и@JsonIgnoreProperties("source")
Указывает, что исходный атрибут игнорируется при сериализации, а источник определен в JDK.EventObject
.
EnvironmentChangeRemoteApplicationEvent
Используется для динамического обновления свойств среды экземпляра службы, которые мы обновляем в базовом приложении.cloud.version
свойство, связанное с событием.
public class EnvironmentChangeRemoteApplicationEvent extends RemoteApplicationEvent {
private final Map<String, String> values;
public EnvironmentChangeRemoteApplicationEvent(Object source, String originService,
String destinationService, Map<String, String> values) {
super(source, originService, destinationService);
this.values = values;
}
...
}
можно увидеть,EnvironmentChangeRemoteApplicationEvent
Реализация класса событий проста. Определена переменная-член типа Map, ключ соответствует имени переменной среды, а значение соответствует обновленному значению.
RefreshRemoteApplicationEvent
Событие обновления конфигурации удаленного приложения используется для получения запроса на удаленное обновление.
public class RefreshRemoteApplicationEvent extends RemoteApplicationEvent {
public RefreshRemoteApplicationEvent(Object source, String originService,
String destinationService) {
super(source, originService, destinationService);
}
}
Унаследовано от абстрактного класса событийRemoteApplicationEvent
, без специальных свойств членов.
AckRemoteApplicationEvent
Подтверждение событий удаленного приложения, которые представляют определенныйRemoteApplicationEvent
Инцидент подтвержден.
public class AckRemoteApplicationEvent extends RemoteApplicationEvent {
private final String ackId;
private final String ackDestinationService;
private Class<? extends RemoteApplicationEvent> event;
public AckRemoteApplicationEvent(Object source, String originService,
String destinationService, String ackDestinationService, String ackId,
Class<? extends RemoteApplicationEvent> type) {
super(source, originService, destinationService);
this.ackDestinationService = ackDestinationService;
this.ackId = ackId;
this.event = type;
}
...
public void setEventName(String eventName) {
try {
event = (Class<? extends RemoteApplicationEvent>) Class.forName(eventName);
} catch (ClassNotFoundException e) {
event = UnknownRemoteApplicationEvent.class;
}
}
}
Класс события находится вRemoteApplicationEvent
На основе определяются свойства члена ackId, ackDestinationService и событие.
ackId и ackDestinationService представляют собой идентификатор времени подтверждения и соответствующей целевой службы соответственно. Событие соответствует типу события, и необходимо подтвердить, что событие может быть подтверждено.RemoteApplicationEvent
Подкласс , поэтому свойство события необходимо проверять при установке значения, и если при преобразовании возникает исключение, оно определяется как неизвестный тип события. Эти события могут прослушиваться любым приложением, которому необходимо реагировать на события шины статистики.
Они ведут себя как обычные события удаленного приложения, т. е. если целевая служба соответствует идентификатору локальной службы, приложение запускает событие в своем контексте.
SentApplicationEvent
Отправка события приложения указывает на то, что куда-то в системе было отправлено удаленное событие.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonIgnoreProperties("source")
public class SentApplicationEvent extends ApplicationEvent {
private static final Object TRANSIENT_SOURCE = new Object();
private final String originService;
private final String destinationService;
private final String id;
private Class<? extends RemoteApplicationEvent> type;
protected SentApplicationEvent() {
// for serialization libs like jackson
this(TRANSIENT_SOURCE, null, null, null, RemoteApplicationEvent.class);
}
public SentApplicationEvent(Object source, String originService,
String destinationService, String id,
Class<? extends RemoteApplicationEvent> type) {
super(source);
this.originService = originService;
this.type = type;
if (destinationService == null) {
destinationService = "*";
}
if (!destinationService.contains(":")) {
// All instances of the destination unless specifically requested
destinationService = destinationService + ":**";
}
this.destinationService = destinationService;
this.id = id;
}
...
}
Вы можете видеть, что класс события наследуется отApplicationEvent
, что само по себе не являетсяRemoteApplicationEvent
События не передаются через шину, а генерируются локально (в основном в ответ на удаленные события). Приложения, которые хотят проводить аудит удаленных событий, могут прослушивать событие, и всеAckRemoteApplicationEvent
Идентификатор в событии получен из соответствующегоSentApplicationEvent
идентификатор определен в . В его определенных свойствах члена есть еще один тип типа события, чем событие удаленного приложения, которое ограниченоRemoteApplicationEvent
подкласс .
UnknownRemoteApplicationEvent
Неизвестное событие удаленного приложения, а такжеRemoteApplicationEvent
Подкласс класса событий. Этот класс события такой же, как и предыдущий.SentApplicationEvent
,AckRemoteApplicationEvent
Связано это с тем, что когда во время сериализации встречается исключение преобразования типа события, оно автоматически создается как неизвестное событие удаленного приложения.
Слушатели событий, а также подписка и публикация сообщений будут обновлены позже. .