SpringCloudAlibaba项目打成war后无法注册到Nacos,无法连接到Nacos Server
- 背景
- 原因
- 解决
- 重新打包、部署:正常!
参考:https://www.jb51.net/article/233940.htm
背景
正常jar(使用内嵌tomcat)包是可以连接并注册到Nacos的,但是将项目改成War(使用外部tomcat)之后
,就不行了;但是项目可正常启动。
原因
Nacos的注册类NacosAutoServiceRegistration 进去之后可以发现它继承了SpringCloud的AbstractAutoServiceRegistration 注册类,在AbstractAutoServiceRegistration 中有一个绑定监听事件,他的作用就是监听到内置容器
启动完成之后获取容器端口向注册中心注册,如下图:
因为这个接口只可以监听内置容器,所以我们就可以得出结论:之所以会出现上面的问题,就是因为使用外部容器时,不会触发监听事件,
所以也就注册不到nacos中。
因此我们可以借助SpringBoot提供的ApplicationRunner接口,这个接口的作用就是在应用启动完成之后执行一些定义好的初始化操作。所以我们可以在服务启动成功之后,通过这个接口将我们的项目注册到Nacos中,下面看代码
解决
import java.lang.management.ManagementFactory;
import java.util.Set;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
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.stereotype.Component;
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
@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) {
//如果getTomcatPort()端口获取异常,就采用配置文件中配置的端口
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;
}
}