微服務探索與實踐—服務註冊與發現

前言

微服務從大規模使用到如今已經有不少年了,從以前的探索到一步步的不斷完善與成熟,微服務已經成爲衆多架構選擇中所必須面對的一個選項。服務註冊與發現是相輔相成的,因此通常會合起來思索。其依託組件有不少,好比Zookeeper,Consul,Eureka等等。程序員

本文,咱們將探討服務註冊和發現的概念及其使用機制,以使得微服務可以在不知道其確切位置(一般是URL)的狀況下消費其餘服務。因爲本文主要是我的實踐的一些總結,總會有不足之處,也但願各位看官幫忙完善。本系列前一篇文章請移步總述面試

服務註冊與發現探討

爲何須要

服務是在具備單獨部署週期的不一樣計算機上運行的單個或較小的代碼庫,可明確解決相關的問題域。不正確的服務設計可能致使重複的服務建立,同時也沒法進行架構層面的複用。sql

若是沒有服務註冊與服務發現,那麼服務的位置將會耦合到消費者服務裏面,最終將會致使整個系統的架構變得死板而又難以維護。事實上,在比較簡單的系統架構裏,採用靜態配置的方式是很是簡單而又效果顯著的,畢竟全部服務都在同一位置,並且不多發生變動。數據庫

而在微服務裏,其目標之一就是使系統可以獨立開發、部署及升級擴展,隨着系統的進一步複雜,服務位置也發生變動,那麼靜態配置就會變得十分雞肋,此時咱們須要變動咱們的策略,那就是在消費其餘服務的時候採用靜態配置。那麼核心問題就來了,服務是如何發現它們索要消費的服務的IP地址和端口號的?既是動態配置,在多實例場景下,配置在專門的系統裏是最好的選擇,ZK和Consul等也就應運而生。緩存

簡單的通訊流程

咱們來看一下一個簡單的服務通訊流程服務器

透過這張圖,咱們能夠知道,服務調用時,無需知道目標服務的真實地址,只須要知道服務Key,而後到服務發現系統裏獲取對應的地址便可。架構

這張圖雖然比較簡單,可是傳遞的信息卻有不少:併發

  • 服務如何肯定自身的IP地址及端口?
  • 在消費方拿到被消費方的地址之後,應採用何種方式調用?
  • 咱們如何添加新服務並刪除已棄用的服務?
  • 若是服務在運行過程當中出現問題,如何快速發現並提早通知?
  • 做爲集中化管理的服務註冊與發現中心掛了,咋整?

服務信息註冊

通常能夠建立服務註冊表,該服務註冊表是服務及其實例及其位置的數據庫。服務實例在啓動時註冊到服務註冊表,並在關閉時註銷。客戶端查詢服務註冊表以查找服務的可用實例。服務註冊表可能會調用服務實例的運行情況檢查API來驗證它是否可以處理請求。咱們已經有了現成的工具,就是Consul等,那麼咱們的關注點就是服務地址的註冊了。負載均衡

最簡單的解決方案就是手動配置。咱們思考一個問題,若是咱們須要對該服務進行水平擴展,再增長一個實例的時候,仍然須要咱們手動配置,可是咱們已經不想手動配置了,在DevOps時代,再使用手動配置,就顯得不那麼專業了,並且人工的介入,也增長了系統運維的成本與風險。運維

因此咱們選擇,自動獲取本機IP地址,可是這裏有一個問題,也是我在實際運用中遇到的問題就是本地會有多個網卡的狀況,這是比較麻煩的,因此那時候我建議每臺機器只配置一個網卡,以減小不肯定性,可是後來,遇到一個新的問題就是,當我想在服務器上安裝代理,以獲取請求包信息的時候,容易改變系統的運行環境,依然存在着不肯定性。後來我在網上查看是否其餘方案的時候,始終沒有一個比較好的解決方案,後來有人說,直接往服務註冊中心發送一個Socket鏈接就能夠了,經過Socket實例獲取本機IP,網上也有人介紹這種方案。

至於端口獲取,相對簡單一點,咱們使用的就是直接配置在服務裏。

服務註冊自己就是要在有限人力干預的狀況下,支持不一樣應用之間的運行與交互。

服務註冊擴展至之其餘信息的註冊

這個地方更多的是考慮服務消費方的負載均衡策略、調用策略以及容錯的可配置性。

在被消費方作了集羣部署的時候,這就是要求咱們根據實際運行狀況及時調整對服務的調用,那麼該如何判斷呢?在實現上能夠考慮權重參數,該參數的設置應該來源於自身以及服務治理系統。

來源於自身,是由於咱們的服務可能部署在相對較差的機器上或者該服務自己只是一個備用系統,不該該承載過大的流量。

來源於服務治理系統,是由於在實際運行中,可能該系統已經出現問題,或者須要暫時下線,咱們能夠設置權重係數爲0,以從消費服務自己來中止對該服務的調用。

權重參數只是其中一個,也是最容易想到和實現的一個,固然還有其餘參數,只要是爲了更好的優化服務間的調用,那麼就能夠註冊進去,同時實現相應的調用策略。好比版本號,TTL等等。

一旦信息多了,就須要考慮如何及時獲取變動,以調整調用策略。

服務發現

服務發現能夠分爲客戶端發現或服務器端發現來肯定要向其發送請求的服務實例的位置。客戶端發現比較簡單一些,直接向服務發現中心獲取所需的被消費者服務的信息。而服務端發現相對來講,比較複雜,須要建立一個路由中心,由路由中心去發現被消費者的請求。咱們這邊用的比較多的是客戶端發現。

確保發現的穩定性,首先就要確保服務註冊中心的穩定性,其地址不該該頻繁發生變化,因此咱們能夠在服務中配置咱們的服務註冊中的地址。此處須要多說明一下,就是做爲服務註冊中心繫統,必定要保持高可用性,能夠經過集羣以及負載均衡來加強可用性。

服務實例的數量及其位置是動態變化的。一般爲虛擬機和容器分配動態IP地址。最複雜的問題天然是如何及時得到被消費者服務變化後的地址?咱們能夠建立一個路由功能,用戶能夠客戶端查詢服務註冊中心以查找服務的可用實例。服務註冊中心可能會調用服務實例的運行情況檢查API來驗證它是否可以處理請求。

咱們在系統啓動的時候,會作個Reload,以加載最新信息。那麼以後如何及時獲取最新信息呢?一般狀況下有兩種,主動輪詢和獲取推送消息。

主動輪詢帶有隨機性,若是偏偏好,可能會很及時,大多數狀況下,可能沒那麼偏偏好,並且還要增長服務發現中心的負載壓力。

推送方式在效果上可能更好一些,在具體實現上可能沒有那麼簡單。

健康檢查

通常而言,健康檢查包括,客戶端心跳和服務端主動探測兩種方式,

首先來講,客戶端心跳,就是客戶端經過TCP或者HTTP的方式,告訴服務端自身的運行狀況,固然客戶端通知是有弊端的,好比客戶端在某一時間點出現故障時,沒法及時通知服務端,過後恢復運行後,告知的也只是當前的運行狀態,即使這時再告訴服務端以前的運行情況,也對服務調用沒有什麼太大意義了,只是對服務自己的運行分析起到了必定做用。即使是保持正常鏈接的狀況下,服務也未必是能夠調用的,好比數據庫掛掉。

通常而言,採用服務端探測的比較多一些,調用方式和客戶端心跳差很少,可是仍然須要咱們注意的是,客戶端所提供的探測接口必須具備通用性,好比能夠查一下次數據庫等等,這樣能夠比較全面的反應系統的運行狀況。

容災與故障轉移

容災的緣由有不少,好比服務再也不使用、雙11大流量的涌進,使得其中一些服務不可用,也就不得不針對性的對一些服務進行容災處理,以集中資源給核心應用。在容災過程當中,能夠給服務下線功能能夠制定一些策略,以豐富功能的使用。.NET Core裏面可使用IApplicationLifetime來顯示下線功能。固然也須要提供手動下線的接口。

容災主要考慮方向是客戶端容災和服務端容災。客戶端容災中,若是服務註冊中心掛掉了,恢復運行可能須要一段時間,在這個過程當中若是保證服務正常運行。在實際運行中很是有可能發生這種狀況,咱們能夠將服務發現中心獲取的信息緩存起來,緩存方式有不少,無外乎是本地內存、文件以及外部存儲,本地內存還要還要考慮該服務重啓過程當中的數據丟失,因此可選的方式就有內存+文件方式。反之,爲了達到容災的要求,咱們能夠在獲取服務發現中心返回的數據的過程當中將數據存在到內存和文件中,能夠採用異步方式存儲。

以下圖所示,在發現過程當中,使用緩存功能,若是緩存都失效了,那就真的要game over一陣子了。

服務端容災,就比較簡單了,由於如今大多數作的都是服務端容災,好比集羣等水平擴展方式, 可主動從其餘節點同步相應的數據,也可等待master的同步。

總結

服務註冊與發如今服務生命週期中發揮着重要做用。動態的服務註冊和發現變得很是重要,它能夠避免服務中斷。在處理服務實例的容災與故障轉移時,儘可能實現自動轉移,並提供手動方式處理,而對於跨服務調用,尤爲是該服務擁有多實例服務的時候,須要考慮負載平衡。

讀者福利

分享免費學習資料

針對於Java程序員,我這邊準備免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)

爲何某些人會一直比你優秀,是由於他自己就很優秀還一直在持續努力變得更優秀,而你是否是還在知足於現狀心裏在竊喜!但願讀到這的您能點個小贊和關注下我,之後還會更新技術乾貨,謝謝您的支持!

資料領取方式:加入Java技術交流羣963944895點擊加入羣聊,私信管理員便可免費領取

如何成爲一個有逼格的Java架構師

怎麼提升代碼質量?——來自阿里P8架構師的研發經驗總結

阿里P8分享Java架構師的學習路線,第六點尤其重要

每一個Java開發者應該知道的八個工具

想面試Java架構師?這些最基本的東西你都會了嗎?

畫個圖來找你的核心競爭力,變中年危機爲加油站

哪有什麼中年危機,不過是把定目標當成了有計劃

被裁人不是寒冬重點,重點是怎麼破解職業瓶頸

相關文章
相關標籤/搜索