SpringCloudWar包部署导致服务未正常注册到Nacos问题

编程

最近把一个 SpringBoot 项目接入了微服务,使用 SpringBoot 2.1.9.RELASE 和 SpringCloud Greewich.SR3 。本地测试都正常,但是上线后,出现了一个这样一个情况:

日志未出现 Nacos Registery 类似的语句,也没有任何异常信息,就像是压根就没有配置微服务一样。

检查了配置文件,正常

本地测试,正常注册

后来找组长帮忙看了一下,发现是 war 包部署的问题:

SpringCloud 项目打 war 包部署时,也就是使用外部 Tomcat 部署,其启动命令、端口等是由外部容器 Tomcat 配置的,而 Nacos 或者其他服务注册方式需要当前项目的端口号用于注册微服务。

以 Nacos 为例,其自动注册微服务的类是 NacosAutoServiceRegistration,我们看一下它的源码:

public class NacosAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {

private NacosRegistration registration;

@Deprecated

public void setPort(int port) {

this.getPort().set(port);

}

protected NacosRegistration getRegistration() {

if (this.registration.getPort() < 0 && this.getPort().get() > 0) {

this.registration.setPort(this.getPort().get());

}

Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");

return this.registration;

}

我们看到 NacosAutoServiceRegistration 使用了 this.registration.setPort(this.getPort().get()); 来设置端口号。

而端口号是从其父类 AbstractAutoServiceRegistration 中的方法获取的:

public abstract class AbstractAutoServiceRegistration<R extends Registration>

implements AutoServiceRegistration, ApplicationContextAware,

ApplicationListener<WebServerInitializedEvent> {

private AtomicInteger port = new AtomicInteger(0);

@Deprecated

public void bind(WebServerInitializedEvent event) {

ApplicationContext context = event.getApplicationContext();

if (context instanceof ConfigurableWebServerApplicationContext) {

if ("management".equals(((ConfigurableWebServerApplicationContext) context)

.getServerNamespace())) {

return;

}

}

this.port.compareAndSet(0, event.getWebServer().getPort());

this.start();

}

这段代码监听了内置容器启动完成事件,监听获取到容器端口后,向注册中心注册服务。

因此,当使用外部容器时,如此处的 Tomcat 来部署项目,AbstractAutoServiceRegistration 就不能监听到容器启动事件了,也就不会尝试向服务注册中心注册当前这个微服务,那么注册就失败了,并且也就没有异常信息了。

解决办法是自定义获取获取外部容器端口的方法, 然后监听应用启动事件,当应用被启动时,获取外部容器启动的端口号,然后将这个 port 设置到 NacosAutoServiceReigistration 中。

下面是完整的解决方法:

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.ApplicationArguments;

import org.springframework.boot.ApplicationRunner;

import org.springframework.cloud.alibaba.nacos.registry.NacosAutoServiceRegistration;

import org.springframework.stereotype.Component;

import javax.management.MBeanServer;

import javax.management.ObjectName;

import javax.management.Query;

import java.lang.management.ManagementFactory;

import java.util.Set;

@Component

public class NacosConfig implements ApplicationRunner {

@Autowired(required = false)

private NacosAutoServiceRegistration registration;

@Value("${server.port}")

Integer port;

@Override

public void run(ApplicationArguments args) {

if (registration != null && port != null) {

Integer tomcatPort = port;

try {

tomcatPort = new Integer(getTomcatPort());

} catch (Exception e) {

e.printStackTrace();

}

registration.setPort(tomcatPort);

registration.start();

}

}

/**

* 获取外部tomcat端口

*/

public String getTomcatPort() throws Exception {

MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();

Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));

String port = objectNames.iterator().next().getKeyProperty("port");

return port;

}

}


交流学习

个人微信:guanlanju6688

个人网站:http://www.eknown.cn

GitHub:https://github.com/laolunsi

公众号:猿生物语,"分享技术,也感悟人生",欢迎关注!

以上是 SpringCloudWar包部署导致服务未正常注册到Nacos问题 的全部内容, 来源链接: utcz.com/z/512223.html

回到顶部