SpringBoot构建war部署到tomcat中无法注册到Nacos服务

本文共 2,659 字,预计阅读时间 9 分钟

最近项目基本开发完成,准备部署到服务器中进行功能的验证,但当把所有的环境都搭建好,启动项目后,tomcat启动日志正常,发现在服务调用时一直报错。

项目是使用SpringBoot框架搭建的,多个项目之间通过nacos进行服务调用。于是我查看的nacos的管理端,发现服务并没有注册进来。开始以为是nacos安装的有问题,仔细去查看了控制台日志和日志文件,都没有发现问题。然后就开始对比本地开发环境和部署环境项目启动时tomcat的打印日志,就发现了问题。

本地开发环境idea的打印日志    

部署环境tomcat的打印日志

可以看到本地是启动时日志打印了注册到nacos的日志,但在部署时并没有打印。于是我想到可能并不是nacos的问题,而是部署的问题,首先就想到可能与tomcat有关,经查询,还真的有这种情况,由于外部tomcat在启动时nacos的监听器没有获取到项目的端口号,就不会尝试向服务注册中心注册当前这个微服务,即使注册失败也没有异常信息。

不如来看下nacos服务注册与发现的源码,其自动注册微服务的类是

看到 NacosAutoServiceRegistration 会设置端口号:

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

在bind的方法中监听了内置容器启动完成事件,获取到容器端口后,向注册中心注册服务。而当使用外部容器Tomcat 来部署项目,bind方法就无法监听到容器启动事件,也就不会尝试向服务注册中心注册当前这个微服务,即使注册就失败了,也没有异常信息。那么该如何处理呢?

既然问题找到了,那么解铃还须系铃人。既然nacos本身无法监听到项目启动,那么我们帮它监听项目的启动然后将项目启动时的端口号取出来给NacosAutoServiceReigistration让其进行注册不就好了吗?

说干就干,大致步骤是在项目初始化时获取端口号并设置给NacosAutoServiceReigistration,然后调用其服务注册的方法。项目初始化的方法很多,这里使用@PostConstruct注解:

新建一个配置类,专门用于系统初始化的操作

复制代码
package com.zxh.config;

import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
import com.alibaba.cloud.nacos.registry.NacosRegistration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * 系统初始化操作
 */
@Configuration
@Slf4j
public class WebAppConfig {

    @Autowired
    private NacosRegistration registration;

    @Autowired
    private NacosAutoServiceRegistration nacosAutoServiceRegistration;
    //获取运行时的环境,dev为本地开发环境
    @Value("${spring.profiles.active}")
    private String env;


    /**
     * 将服务注册到nacos
     */
    @PostConstruct
    public void nacosServerRegister() {
        if (registration != null && StrUtil.isNotEmpty(env) && !env.equals("dev")) {
            try {
                Integer tomcatPort = new Integer(getTomcatPort());
                //设置端口号
                registration.setPort(tomcatPort);
                //将服务注册到nacos
                nacosAutoServiceRegistration.start();
            } catch (Exception e) {
                log.error("获取外部Tomcat端口异常:{}", e);
            }
        }
    }

    /**
     * 获取外部tomcat端口
     *
     * @return
     */
    public static 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;
    }

}
复制代码

加入此类后,本地开发环境不影响,重新打war包部署到tomcat并启动tomcat,发现服务已经注册成功。

posted @   钟小嘿  阅读(2366)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示