Spring boot项目打包war部署外部tomcat无法注册到Nacos

当Springboot项目被打包成war并部署到外部Tomcat时,服务无法自动注册到Nacos。原因是外部容器启动不触发内部的WebServerInitializedEvent事件。解决方法是在应用启动时通过ApplicationRunner手动注册服务,获取并设置Tomcat端口。
摘要由CSDN通过智能技术生成

现象

Spring boot 或者 Spring cloud 项目,如果用默认的打包jar, 使用内嵌的tomcat 启动,可以正常注册到Nacos 注册中心。
如果打包为war,部署到外部tomcat, 调用正常,消费者可以调用到 生产者服务,但是Nacos 后台的服务列表里没有显示。很诡异。。。

分析

查看源码,需从nacos的注册类找起,查找后发现,nacos注册类NacosAutoServiceRegistration继承了Spring Cloud中AbstractAutoServiceRegistration, 而在AbstractAutoServiceRegistration中绑定了一个监听事件,监听内置容器启动完成事件,监听到获取容器端口后向注册中心注册。


@EventListener({WebServerInitializedEvent.class})
public void bind(WebServerInitializedEvent event) {
    ApplicationContext context = event.getApplicationContext();
    if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
        this.port.compareAndSet(0, event.getWebServer().getPort());
        this.start();
    }
}

而使用外部容器时,不能监听到事件,所以自动注册失败。

解决方法

使用ApplicationRunner在服务启动完成后,加载注册。

import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
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 javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
import java.lang.management.ManagementFactory;
import java.util.Set;

/**
 * @author liushengbing
 * @version 1.0.0
 * @ClassName NacosRegisterOnWar.java
 * @Description 项目打包war情况下部署外部tomcat,需要该方式注册nacos
 * @createTime 2021年07月08日 16:36
 */
@Component
public class NacosRegisterOnWar implements ApplicationRunner {

    @Autowired(required = false)
    private NacosAutoServiceRegistration registration;

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


    /**
     * Callback used to run the bean.
     *
     * @param args incoming application arguments
     * @throws Exception on error
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        if(registration != null && port != null){
            Integer tomcatPort = port;
            try{
                tomcatPort = new Integer(getTomcatPort());
                registration.setPort(tomcatPort);
                registration.start();
            }catch(Exception e){
                System.out.println("使用内置tomcat启动,不需要单独注册nacos服务");
            }
        }
    }

    /**
     * @Author liushengbing
     * @Description 获取外部tomcat端口
     * @Date 2021/7/8 16:43
     * @Param
     * @return
     */
    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;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值