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,发现服务已经注册成功。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!