最近本身嘗試着搭建springcloud項目,果不其然,剛開始就踩坑了,仍是那種一臉懵逼的坑。搭建後程序能正常運行註冊到eureka註冊中心,但註冊好以後便會當即註銷掉。剛開始認爲是線程拋異常掛掉了,便致使服務註銷了。而後各類debug排查,最後發現是正常退出。至於具體緣由,我下面作個詳細解釋。web
這裏註冊中心啓動是徹底沒問題的,問題就出在client啓動,啓動日誌以下:spring
看上面的日誌能夠觀察到,服務最開始是有正常註冊到eureka註冊中心的,可是緊接着會發現。Unregistering application EUREKA-CLIENT with eureka with status DOWN,後面接着 Shutting down DiscoveryClient ... 最後 Unregistering ...。tomcat
看日誌並未發現很明顯的異常,而後debug調試一波,無任何錯誤發現。便隨手google了一下。果真仍是有小夥伴曾經也有遇到過一樣的問題的。網上的解決辦法以下:
在client端pom中加上依賴:
固然,這也只是其中的一個解決辦法。其實出現上述狀況的緣由是JVM隨着主線程的結束而退出了。容器close時會觸發DiscoveryClient的shutdown方法,便會註銷已註冊的節點。可是加上web依賴後,就拿tomcat來舉例說明,隨着springboot項目的啓動,會建立一個WebServer:
springboot
我們重點關注下initialize方法中的:
看源碼上的註釋,便會發現這裏開啓了一個用戶線程(非守護線程),這樣主線程退出後JVM也不會退出。也就不會觸發註銷節點的動做。app
其實解決這個問題的辦法仍是很簡單的,只要你能保證由一個正常的用戶線程存在就好了,有可能我們本身的提供服務的應用不須要用到tomcat這樣的web容器,而是像其餘rpc服務同樣調用時,我們即可以本身建立一個用戶線程便可(默認構造出來的線程都是用戶線程,除非你調用setDaemon方法將其daemon屬性設置成true纔會變成守護線程)。而後我們本身內部提供一個狀態值可讓其正常退出便可。
下面寫個簡單的例子:
google
經過此次的踩坑,仍是彌補了本身對JVM理解的一些盲區。好比當進程中只要還有一個用戶線程存在時,進程便不會當即結束。只有當進程中只存在守護線程或者不存在任何線程的狀況下,進程纔會立刻結束。咱們一般瞭解到的相似gc的操做線程,即是守護線程,這樣我們本身的業務線程在異常狀況下掛掉,進程也會隨之結束。線程