SpringCloud War 包部署導(dǎo)致服務(wù)未正常注冊到 Nacos 問題

最近把一個 SpringBoot 項(xiàng)目接入了微服務(wù),使用 SpringBoot 2.1.9.RELASE 和 SpringCloud Greewich.SR3 。本地測試都正常,但是上線后千诬,出現(xiàn)了一個這樣一個情況:

日志未出現(xiàn) Nacos Registery 類似的語句,也沒有任何異常信息,就像是壓根就沒有配置微服務(wù)一樣丁侄。

檢查了配置文件,正常

本地測試朝巫,正常注冊

后來找組長幫忙看了一下鸿摇,發(fā)現(xiàn)是 war 包部署的問題:

SpringCloud 項(xiàng)目打 war 包部署時(shí),也就是使用外部 Tomcat 部署劈猿,其啟動命令拙吉、端口等是由外部容器 Tomcat 配置的,而 Nacos 或者其他服務(wù)注冊方式需要當(dāng)前項(xiàng)目的端口號用于注冊微服務(wù)揪荣。

以 Nacos 為例筷黔,其自動注冊微服務(wù)的類是 NacosAutoServiceRegistration,我們看一下它的源碼:

public class NacosAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {

    private NacosRegistration registration;

    @Deprecated
    public void setPort(int port) {
        this.getPort().set(port);
    }

    protected NacosRegistration getRegistration() {
        if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
            this.registration.setPort(this.getPort().get());
        }

        Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
        return this.registration;
    }

我們看到 NacosAutoServiceRegistration 使用了 this.registration.setPort(this.getPort().get()); 來設(shè)置端口號仗颈。

而端口號是從其父類 AbstractAutoServiceRegistration 中的方法獲取的:

public abstract class AbstractAutoServiceRegistration<R extends Registration>
        implements AutoServiceRegistration, ApplicationContextAware,
        ApplicationListener<WebServerInitializedEvent> {

    private AtomicInteger port = new AtomicInteger(0);


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

這段代碼監(jiān)聽了內(nèi)置容器啟動完成事件佛舱,監(jiān)聽獲取到容器端口后,向注冊中心注冊服務(wù)挨决。

因此请祖,當(dāng)使用外部容器時(shí),如此處的 Tomcat 來部署項(xiàng)目凰棉,AbstractAutoServiceRegistration 就不能監(jiān)聽到容器啟動事件了损拢,也就不會嘗試向服務(wù)注冊中心注冊當(dāng)前這個微服務(wù),那么注冊就失敗了撒犀,并且也就沒有異常信息了福压。

解決辦法是自定義獲取獲取外部容器端口的方法, 然后監(jiān)聽?wèi)?yīng)用啟動事件或舞,當(dāng)應(yīng)用被啟動時(shí)荆姆,獲取外部容器啟動的端口號,然后將這個 port 設(shè)置到 NacosAutoServiceReigistration 中映凳。

下面是完整的解決方法:

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.cloud.alibaba.nacos.registry.NacosAutoServiceRegistration;
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;

@Component
public class NacosConfig implements ApplicationRunner {

    @Autowired(required = false)
    private NacosAutoServiceRegistration registration;

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

    @Override
    public void run(ApplicationArguments args) {
        if (registration != null && port != null) {
            Integer tomcatPort = port;
            try {
                tomcatPort = new Integer(getTomcatPort());
            } catch (Exception e) {
                e.printStackTrace();
            }

            registration.setPort(tomcatPort);
            registration.start();
        }
    }

    /**
     * 獲取外部tomcat端口
     */
    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;
    }
}

交流學(xué)習(xí)

個人微信:guanlanju6688

個人網(wǎng)站:http://www.eknown.cn

GitHub:https://github.com/laolunsi

公眾號:猿生物語胆筒,"分享技術(shù),也感悟人生",歡迎關(guān)注仆救!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抒和,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子彤蔽,更是在濱河造成了極大的恐慌摧莽,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顿痪,死亡現(xiàn)場離奇詭異镊辕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蚁袭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門征懈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揩悄,你說我怎么就攤上這事卖哎。” “怎么了虏束?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵棉饶,是天一觀的道長。 經(jīng)常有香客問我镇匀,道長照藻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任汗侵,我火速辦了婚禮幸缕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晰韵。我一直安慰自己发乔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布雪猪。 她就那樣靜靜地躺著栏尚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪只恨。 梳的紋絲不亂的頭發(fā)上译仗,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機(jī)與錄音官觅,去河邊找鬼纵菌。 笑死,一個胖子當(dāng)著我的面吹牛休涤,可吹牛的內(nèi)容都是我干的咱圆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼序苏!你這毒婦竟也來了手幢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤杠览,失蹤者是張志新(化名)和其女友劉穎弯菊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踱阿,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年钦铁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了软舌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡牛曹,死狀恐怖佛点,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情黎比,我是刑警寧澤超营,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站阅虫,受9級特大地震影響演闭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颓帝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一米碰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧购城,春花似錦吕座、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至侮攀,卻和暖如春锣枝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背魏身。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工惊橱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人箭昵。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓税朴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子正林,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容