Spring Cloud Consul
2.1.x 在 Tomcat 容器中没有注册服务,但是在本地开发的时候是没问题的。
Spring Cloud
2.1.x 注册服务, 是通过发布org.springframework.boot.web.context.WebServerInitializedEvent
事件实现的, 参考 org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationListener
。
org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationListener
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
if (applicationEvent instanceof WebServerInitializedEvent) {
WebServerInitializedEvent event = (WebServerInitializedEvent) applicationEvent;
ApplicationContext context = event.getApplicationContext();
if (context instanceof ConfigurableWebServerApplicationContext) {
if ("management".equals(
((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {
return;
}
}
this.autoServiceRegistration.setPortIfNeeded(event.getWebServer().getPort());
this.autoServiceRegistration.start();
}
}
该事件仅在内嵌 Tomcat
中生效,参考 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
, 而通过 Tomcat
容器启动服务时监听不到该事件。
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
protected void finishRefresh() {
super.finishRefresh();
WebServer webServer = this.startWebServer();
// 这里在 内嵌Tomcat 启动后,webServer 不为 null ,发布 ServletWebServerInitializedEvent 事件,触发 ConsulAutoServiceRegistrationListener 注册服务
// 这里在 Tomcat 容器启动服务 后,webServer 是 null 的,因此导致 ConsulAutoServiceRegistrationListener 接收不到对应的事件,从而无法服务注册
if (webServer != null) {
this.publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
增加一个 ApplicationListener
监听 ApplicationReadyEvent
, 在应用启动准备好后注册服务。 逻辑参考 org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationListener
。
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.consul.ConditionalOnConsulEnabled;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* Spring Cloud 2.1 注册服务, 通过发布 {@link org.springframework.boot.web.context.WebServerInitializedEvent} 事件实现的, 参考 {@link
* org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationListener}。
*
* <p>
* 该事件仅在内嵌 Tomcat 中生效,参考 {@link org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext}, 而通过
* Tomcat 容器启动服务时监听不到该事件。
* </p>
*
* @author Sven Augustus
*/
@Component
@ConditionalOnConsulEnabled
@RequiredArgsConstructor
public class ConsulAutoServiceRegistrationInitializerListener implements ApplicationListener<ApplicationReadyEvent> {
private final ConsulAutoServiceRegistration consulAutoServiceRegistration;
private final ConsulDiscoveryProperties properties;
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
consulAutoServiceRegistration.start();
}
}
by Sven Augustus https://my.oschina.net/langxSpirit