Spring-cloud微服務實戰【三】:eureka註冊中心(中)
回憶一下,在上一篇文章中,我們建立了兩個springboot專案,並且在consumer專案中通過restTemplate進行HTTP通訊,成功訪問到了producer提供的介面,思考一下這樣的實現方式有什麼問題?
1.consumer必須知道producer的IP,才能呼叫對方的HTTP介面,並且在consumer程式碼中使用硬編碼的方式來訪問producer的HTTP介面,程式碼耦合度高,實現方式不優雅.也許有童鞋會說,我們可以在application.properties配置檔案進行配置,那麼請看第二個問題.
2.一般來說,生產環境的producer是一個叢集,有多個IP,那我consumer該怎麼寫請求地址?並且假如producer叢集的IP變了,consumer應用需要修改配置,重新打包上線.這對於一個高併發訪問的生產專案來說是不可接受的.因此,consumer應用需要一種機制,可以在訪問producer的時候不需要關心producer的IP,並且該機制還應該提供類似於觀察者模式的通知機制,在producer的IP進行變更的時候,及時通consumer,並且還能提供類似Nginx的負載均衡的功能,這就是eureka註冊中心的作用.
什麼是eureka註冊中心?
eureka是netflix公司開發的一款用於服務發現的框架,spring-cloud將其整合到spring-cloud-netflix子專案中,包括我們後續會使用的負載均衡ribbon,服務熔斷與降級Hystrix等等都是netflix公司開發的.可以看出,springcloud其實整合了許多優秀公司的框架.
我們通過一張圖來說明一下eureka工作機制:
假如我們現在有許多的微服務作為服務提供方,每個微服務是一個叢集,他們將自己的叢集節點的IP與埠號註冊到eureka中心,當有消費者需要消費服務的時候,即可從註冊中心拉取所有的服務提供方列表,選擇需要消費的服務,此時,eureka會根據負載演算法將消費者需要的服務的IP與埠號返回給消費者,此時,消費者就可以根據IP和埠號去消費對應的服務了.此外,eureka還必須接收註冊服務的心跳,確保註冊的服務可用.並且從圖中我們可以得知:
程式碼實戰
接下來,我們改造上一篇文章中已有的程式碼,使用eureka進行服務治理,producer註冊自身到eureka,consumer從eureka獲取producer的資訊並呼叫.
首先,我們要新建一個子模組,用於充當eureka-server的角色:
將本模組加入父專案中:
然後新增pom.xml中的配置:
修改配置檔案:
然後在啟動類加上@EnableEurekaServer:
然後啟動試一試,此時控制檯會有錯誤資訊:
我們暫時先不管這些錯誤資訊,先訪問一下,看看是否能訪問:
可以看到,eureka是能正常訪問的,接下來,我們修改producer的程式碼,將producer註冊到eureka-server中.
首先修改pom.xml:
然後修改配置檔案:
最後在啟動類加上@EnableEurekaClient:
此時,我們再啟動producer專案,然後訪問eureka-server,看看是否producer已經註冊成功:
此時我們再訪問該頁面,我們需要關注的主要是筆者使用紅框標識的3條資訊,其中第一條我們暫時先不管(第一次訪問頁面不會出現,但過一會兒重新整理就可以看到),待會兒我們再倒回來說,第二條,表示我們的producer應用已經註冊到eureka-server,但應用名未設定,所以目
前顯示的是UNKNOWN,因此需要我們設定應用名.第三條狀態為UP(1),表示該服務正常啟動,且地址是: DongHP:7001,點選訪問試一試:
可以看到,訪問的域名是donghp(我的電腦名是DongHP):7001,後面跟的是actuator/info,並且頁面報錯,報錯資訊提示我們沒有該頁面(404),因此我們需要新增spring-actuator,該模組是spring進行健康檢查的模組,我們先分別解決第二和第三個問題:先修改配置檔案,新增應用名:dhp-micro-service-producer
接下來為了讓我們看到真實的IP地址,而不是 donghp:7001 ,我們再加上顯示真實IP的配置:
最後,再新增spring-actuator健康檢查的依賴:
再重啟producer,並重新整理eureka-server頁面:
可以看到,修改後的producer已經成功註冊到eureka-server中了,但是我們會發現,之前註冊的服務還在,並沒有消失,這是什麼原因呢?是快取嗎?並不是,我們可以試一試,過一會兒再重新整理,仍然還是有,這並不是快取,還記得我們之前所說的第一條:
提示資訊嗎?這是eureka提示我們觸發了eureka的自我保護機制.
所謂eureka自我保護機制,就是當服務未按時進行心跳續約時(之前我們在介紹eureka的時候說了,服務如果註冊到eureka後,會定時向eureka傳送心跳),Eureka會統計服務例項最近15分鐘心跳續約的比例是否低於了85%(eureka.server.renewal-percent-threshold預設情況下=0.85)。當server在15分鐘內,比值低於percent,即少了15%的微服務心跳,server會進入自我保護狀態,Self-Preservation。在此狀態下,server不會刪除任何註冊資訊,這就有可能導致在呼叫微服務時,實際上服務並不存在。由此我們可以分析出eureka自我保護機制的缺點:有可能保留確實已經不可用的微服務,但是相比之下,它的優點是能最大化儲存所有的微服務,因為在生產環境下,網路問題導致的心跳丟失太常見了,我們不能簡單以是否收到心跳來判斷一個微服務是否不可用,因此建議生產環境開啟自我保護機制,開發時的測試環境可以關閉.
因此上圖中出現的問題就能夠解釋了,首先我們已經關閉了之前的UNKNOWN的微服務,重新修改配置啟動了新的DHP-MICRO-SERVICE-PRODUCER,此時eureka伺服器並沒有重啟,UNKNOWN的微服務不再向eureka傳送心跳(預設30秒傳送一次心跳),因此eureka的心跳比例只有50%,低於85%,頁面彈出eureka觸發自我保護機制的提示,並且eureka進入自我保護狀態,不會刪除任何微服務.因此不管我們如何重新整理頁面,UNKNOWN的微服務始終都在,如果需要禁用eureka的自我保護狀態,可以使用配置:eureka.server.enable-self-preservation=false(預設是開啟的).
此時先啟動eureka-server,再還原producer的配置啟動,再修改producer的配置啟動:
上圖中①提示我們目前關閉了自我保護模式,②說明目前有兩個已註冊的微服務,但是UNKNOWN已經下線了,因此我們過一分鐘重新整理:
此時就只有一個了,我們再訪問一下:
得出兩個資訊:
1.我們的ip是192.168.1.105,去驗證一下:
2.我們沒有配置健康檢查的資訊,因此我們在producer中配置相關資訊:
到此,我們的eureka-server已經成功啟動,並且producer也註冊到eureka了,一切看似很完美了,但大家是否記得之前我們說eureka-server啟動的時候會報錯的問題呢?
這是因為eureka-server配置還不完整,我們還需要新增配置:
然後再啟動eureka-server和producer:
可以看到,producer服務已經成功註冊到eureka中了,並且eureka-server也沒有報錯資訊了.
此時我們再通過consumer專案驗證一下.修改consumer專案程式碼:
首先consumer也需要新增eureka-client的依賴:
其次配置eureka相關資訊:
然後在啟動類加上註解:
最後修改程式碼:
可以發現,這裡以前是直接使用ip:port,現在通過eureka發現服務,就對應於我們之前所說的不再關心對方服務的ip和埠,並且對方服務地址變化也不會再對我們的程式碼造成任何影響了,程式碼的優雅性和可維護性大大提升!
由於這種方式走eureka服務發現,因此還需要加上@LoadBalanced註解:
最後測試一下:
訪問成功!自此,我們成功使用了eureka註冊中心來解決文章一開始丟擲的兩個問題,那是不是這樣就完美了?是否還有值得繼續優化的地方?敬請期待下一篇文章.
本文的github地址
本文由部落格一文多發平臺 OpenWrite 釋出!