首頁  >  文章  >  Java  >  SpringBoot部署到外部Tomcat無法註冊到Nacos服務端如何解決

SpringBoot部署到外部Tomcat無法註冊到Nacos服務端如何解決

WBOY
WBOY轉載
2023-05-13 23:13:042394瀏覽

事情經過

近期做一個專案投標演示(POC)環境支持,需要整合Nacos服務端。考慮到現有專案中已經有了Nacos相關依賴,那還不簡單?新建個服務端,配置幾下重啟不就搞定了嗎?然而事情遠遠沒有想得這麼簡單。同樣的程式碼在我本地IDE裡運作就能註冊成功,在示範環境 Tomcat War 部署就不行了。

經過遠端Debug程式碼,發現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 成功後,才會發布WebServerInitializedEvent 事件。而Nacos客戶端在等這個事件出現才會向服務端註冊自己。又因為部署在外部Tomcat中就不會初始化內嵌Tomcat,也就沒觸發這個事件。

所以解決方法就是將Nacos等事件的部分程式碼呼叫下,讓他們啟動註冊。

Nacos的自動註冊類別是NacosAutoServiceRegistration,它繼承Spring Cloud的AbstractAutoServiceRegistration#,在AbstractAutoServiceRegistration#等的bind(WebSerEventInitialized) 方法監聽事件,設定連接埠號碼並啟動註冊。這裡邊 this.port 是從事件中取得的,需要我們自行取得。

SpringBoot部署到外部Tomcat無法註冊到Nacos服務端如何解決

設定port的位置可見,是從org.springframework.cloud.client.serviceregistry.Registration中取到的,給它設定一下就可以了。

SpringBoot部署到外部Tomcat無法註冊到Nacos服務端如何解決

解決方法

我寫了一個完整的設定類別放到了這個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);
    }
 
}

以上是SpringBoot部署到外部Tomcat無法註冊到Nacos服務端如何解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除