SpringBoot部署到外部Tomcat無法注冊到Nacos服務端的解決思路
事情經(jīng)過
近期做一個項目投標演示(POC)環(huán)境支持,需要集成Nacos服務端??紤]到現(xiàn)有項目中已經(jīng)有了Nacos相關依賴,那還不簡單?新建個服務端,配置幾下重啟不就搞定了嗎?然而事情遠沒有想得這么簡單。同樣的代碼在我本地IDE里運行就能注冊成功,在演示環(huán)境 Tomcat+War 部署就不行了。
經(jīng)過遠程Debug代碼,發(fā)現(xiàn)Nacos客戶端的線程都有啟動,卻沒有注冊成功。
思路
想到可能與Tomcat部署模式有關系,就去查了官方issue和StackOverFlow
The event is published as part of Spring Boot starting the embedded Tomcat instance. If you're deploying to an external container, there's no embedded container to start and, therefore, no event is published. – Andy Wilkinson
大致是說只有當 Spring Boot 啟動內嵌 Tomcat 成功后,才會發(fā)布 WebServerInitializedEvent
事件。而Nacos客戶端在等這個事件出現(xiàn)才會向服務端注冊自己。又因部署在外部Tomcat中就不會初始化內嵌Tomcat,也就沒觸發(fā)這個事件。
所以解決方法就是將Nacos等事件的部分代碼調用下,讓他們啟動注冊。
Nacos的自動注冊類是 NacosAutoServiceRegistration
,它繼承Spring Cloud的AbstractAutoServiceRegistration
,在AbstractAutoServiceRegistration
等的 bind(WebServerInitializedEvent)
方法監(jiān)聽事件,設置端口號并啟動注冊。這里邊 this.port
是從事件中獲取的,需要我們自行獲取。
設置port的位置可見,是從org.springframework.cloud.client.serviceregistry.Registration
中取到的,給它設置一下就可以了。
解決辦法
我寫了一個完整的配置類放到了該ISSUE下邊,這里直接貼在下邊。
import java.lang.management.ManagementFactory; import java.util.Set; import javax.annotation.PostConstruct; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.Query; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration; import com.alibaba.cloud.nacos.registry.NacosRegistration; @Configuration public class NacosWarDeployConfig { private static final Logger logger = LoggerFactory.getLogger(NacosWarDeployConfig.class); @Autowired private Environment env; @Autowired private NacosRegistration registration; @Autowired private NacosAutoServiceRegistration nacosAutoServiceRegistration; @PostConstruct public void nacosServerRegister() { if (registration != null) { registration.setPort(getTomcatPort()); nacosAutoServiceRegistration.start(); } } public int getTomcatPort() { try { return getProvideTomcatPort(); } catch (Exception e) { logger.warn("obtain provide tomcat port failed, fallback to embeded tomcat port."); } return getEmbeddedTomcatPort(); } private int getProvideTomcatPort() throws MalformedObjectNameException, NullPointerException { 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 Integer.valueOf(port); } private int getEmbeddedTomcatPort() { return env.getProperty("server.port", Integer.class, 8080); } }
經(jīng)過我這一波操作問題終于解決了。我是Hellxz,不在進坑就在爬坑的路上。
到此這篇關于SpringBoot部署到外部Tomcat無法注冊到Nacos服務端的文章就介紹到這了,更多相關SpringBoot無法注冊到Nacos服務端內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java8中Stream?API的peek()方法詳解及需要注意的坑
這篇文章主要給大家介紹了關于Java8中Stream?API的peek()方法詳解及需要注意的坑,Java 中的 peek 方法是 Java 8 中的 Stream API 中的一個方法,它屬于中間操作,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-06-06SpringMVC中RequestContextHolder獲取請求信息的方法
這篇文章主要介紹了SpringMVC中RequestContextHolder獲取請求信息的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04Springboot結合Flowable實現(xiàn)工作流開發(fā)
本文主要介紹了Springboot結合Flowable實現(xiàn)工作流開發(fā),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01