本文分享自国内优秀IT教育——【优锐课】
通过此常见问题解答指导教程回答有关Spring Cloud Bus的一些基本问题。
“ Spring Cloud Bus将分布式系统的节点与轻量级消息代理链接在一起。然后可以将其用于广播状态更改(例如配置更改)或其他管理指令。”
介绍
上面的声明是Spring Cloud网站上的定义。 在简短定义之后,有一个简单的示例。
我希望像我一样,你们中的许多人希望对这项新功能有更多的了解。
例如,以下是我对Spring Cloud Bus的疑问:
• 消息如何发送?
• 如何收到消息?
• 目的地如何匹配?
• 收到消息后如何触发动作?
在本文中,我将通过一个可靠的代码示例分享对Spring Cloud Bus的理解。
代码示例
我对此进行解释的假设是,由于Spring Cloud Stream已经存在了很长时间,因此我们已经很熟悉了。Spring Cloud Bus构建在其之上。
让我们从SpringCloudBusClient接口定义开始。
public interface SpringCloudBusClient {
String INPUT = "springCloudBusInput";
String OUTPUT = "springCloudBusOutput";
@Output(SpringCloudBusClient.OUTPUT)
MessageChannel springCloudBusOutput();
@Input(SpringCloudBusClient.INPUT)
SubscribableChannel springCloudBusInput();
}
在界面中,我们创建了两个绑定: springCloudBusInput和springCloudBusOutput . 注释 @input和 @output 源自@EnableBinding 注释。
可以通过配置文件修改springCloudBusInput 和 springCloudBusOutput的属性(即主题)。
spring.cloud.stream.bindings:
springCloudBusInput:
destination: my-bus-topic
springCloudBusOutput:
destination: my-bus-topic
接下来是代码示例的主体:
// BusAutoConfiguration
@EventListener(classes = RemoteApplicationEvent.class) ❶
public void acceptLocal(RemoteApplicationEvent event) {
if (this.serviceMatcher.isFromSelf(event)
&& !(event instanceof AckRemoteApplicationEvent)) { ❷
this.cloudBusOutboundChannel.send(MessageBuilder.withPayload(event).build()); ❸
}
}
@StreamListener(SpringCloudBusClient.INPUT) ❹
public void acceptRemote(RemoteApplicationEvent event) {
if (event instanceof AckRemoteApplicationEvent) {
if (this.bus.getTrace().isEnabled() && !this.serviceMatcher.isFromSelf(event)
&& this.applicationEventPublisher != null) { ❺
this.applicationEventPublisher.publishEvent(event);
}
// If it's an ACK we are finished processing at this point
return;
}
if (this.serviceMatcher.isForSelf(event)
&& this.applicationEventPublisher != null) { ❻
if (!this.serviceMatcher.isFromSelf(event)) { ❼
this.applicationEventPublisher.publishEvent(event);
}
if (this.bus.getAck().isEnabled()) { ❽
AckRemoteApplicationEvent ack = new AckRemoteApplicationEvent(this,
this.serviceMatcher.getServiceId(),
this.bus.getAck().getDestinationService(),
event.getDestinationService(), event.getId(), event.getClass());
this.cloudBusOutboundChannel
.send(MessageBuilder.withPayload(ack).build());
this.applicationEventPublisher.publishEvent(ack);
}
}
if (this.bus.getTrace().isEnabled() && this.applicationEventPublisher != null) { ❾
// We are set to register sent events so publish it for local consumption,
// irrespective of the origin
this.applicationEventPublisher.publishEvent(new SentApplicationEvent(this,
event.getOriginService(), event.getDestinationService(),
event.getId(), event.getClass()));
}
}
上面代码的注释:
- Spring事件监听器将监视所有RemoteApplicationEvent事件。例如,bus-env将发送 EnvironmentChangeRemoteApplicationEvent,而bus-refresh将发送RefreshRemoteApplicationEvent。所有这些事件都将被捕获。
- 检查 AckRemoteApplicationEvent是否为远程事件,而sender是否为事件本身。如果是这样,请继续执行步骤3。
- 使用事件作为有效内容编写消息。然后通过springCloudBusOutput将消息发送给代理。
- @StreamListener 注释 springCloudBusInput 以接收远程事件。
- 如果远程事件是AckRemoteApplicationEvent,并且打开了跟踪,但是该事件本身未发送,则AckRemoteApplicationEvent将确认事件的接收。那将是流程的结束。
- 如果不满足步骤5的要求,则表示事件确实是远程的,请转至7和8;否则,请转至7。否则,执行步骤9。
- 将事件作为本地事件发送。
- 如果AckRemoteApplicationEvent处于打开状态,则编写 AckRemoteApplicationEvent并将其发送到本地和代理。
- 如果打开了跟踪,则编写并发送 SentApplicationEvent .
通过此示例,我们得到了上述问题的答案:
• 消息如何发送?
使用BusAutoConfiguration#acceptLocal将消息发送到springCloudBus中定义的主题。
• 如何收到消息?
BusAutoConfiguration#acceptRemote将接收来自springCloudBus主题的消息。
• 目的地如何匹配?
BusAutoConfiguration#acceptRemote与目的地匹配。
• 收到消息后如何触发动作?
在该示例中,EnvironmentChangeListener首先接收EnvironmentChangeRemoteApplicationEvent,然后操作逻辑可以相应地采取行动。
小结
Spring Cloud Bus仍然很新。 但是,它基于Spring事件和Spring Cloud Stream构建,因此不难理解其背后的逻辑。
目前,Bus上只有少数远程事件可用,其中大多数是配置更新。 用户可以使用@RemoteApplicationEventScan注释扩展RemoteApplicationEvent来构建自己的微服务消息传递系统。
本文分享到这。
有想要JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java学习资料和视频课程的童鞋也可以加vx:ddmsiqi 领取啦,共同进步~
抽丝剥茧 细说架构那些事——【优锐课】