html
客戶端-------IP+port------>服務端1web
-------IP+port------>服務端2算法
-------IP+port------>服務端N數據庫
可是,若是服務發現能夠將服務端網絡位置信息都集中起來,這樣客戶端能夠根據想要調用的服務的名稱,就能夠得到其服務的IP和port。安全
客戶端-------服務名------->服務發現<---------註冊IP+port-----------服務端N服務器
客戶端<-----IP+port-------服務發現網絡
爲何服務發現能夠保存全部服務端的IP+port呢?由於內部有一張服務註冊表,這是一個可用服務實例的數據庫,服務註冊表提供管理API和查詢API功能,服務實例則使用管理API從服務註冊表中註冊和註銷,系統組件使用查詢API來發現可用的服務實例。session
服務註冊表的特性是高度可用和最新,eureka的作法是提供一個 用於註冊和查詢服務實例的REST API,服務實例使用POST請求註冊其網絡位置,每隔30s就使用PUT請求刷新其註冊信息。而consul使用的是健康監測。框架
如下是主流IP地址的獲取方式:運維
手動配置須要註冊的IP,也就是寫配置文件,固然這種寫死的方法在微服務中是不可行的,由於微服務基本都是支持水平擴容多機部署的,這種方法會帶來運維上不少的不便。
經過遍歷網卡的方式去獲取,找到第一個不爲本地環回地址的IP地址。
在一些網絡規劃比較好的標準化機房中,能夠經過手動指定網卡名的方式,指定使用哪一塊網卡所對應的的IP地址進行註冊。
直接與服務註冊中心創建socket鏈接,經過socket.getLocalAddress()方式獲取本機IP。
端口的獲取方式,沒有標準化方案。
若是是RPC應用,啓動的時候都會有一個配置來指定服務監聽端口,註冊的時候能夠直接使用配置項的端口值。
傳統的WEB容器所提供的HTTP應用,也會有一個配置文件來配置容器的監聽端口,註冊時能夠直接使用配置項的端口值。
在Java應用的SpringBoot框架中,能夠經過(SpringBoot版本爲1.x)EmbeddedServletContainerInitiallizedEvent.getEmbeddedServletContainer().getPort()來獲取。
consul是一個支持多數據中心分佈式可高用,用於服務發現和配置共享的工具,採用Raft算法保證服務的一致性,且支持健康檢查。
服務發現:經過DNS或HTTP方式獲取服務信息。
健康檢查:能夠提供與給定服務相關聯的任何數量的健康檢查(如web狀態碼或cpu使用率)。
K/V存儲:能夠經過consul存儲如動態配置之類的相關信息。
多數據中心:支持多數據中心,開箱即用。
WEB UI:經過web頁面便可瞭解服務如今的運行狀況,一目瞭然。
圖中不管是CLIENT仍是SERVER都算是一個節點,consul集羣是由N個SERVER和M個CLIENT組成的。
CLIENT是consul的client模式,在這種模式下,全部註冊到當前節點的服務都會被轉發到SERVER,自己是不持久化這些信息。
SERVER是consul的server模式,功能與CILENT相同,但惟一不一樣的是它會將全部信息持久化到本地,這樣遇到故障,信息是能夠被保留並使用的。SERVER節點還參與Raft、維護會員信息、註冊服務、健康檢查等功能。
SERVER-LEADER代表它管理整個集羣的SERVER,它負責同步註冊的信息給其餘SERVER,同時也要負責各個節點的健康檢測。
LAN Gossip池包含了這個數據中心的全部節點,這樣就不須要給客戶端配置服務器地址,它能夠自動完成,並且每一個節點均可以進行節點故障檢查,也能夠進行事件廣播。
WAN Gossip池包含了全部的SERVER(不包含CLIENT),這些服務器主要位於不一樣的數據中心,一般經過互聯網或廣域網進行通訊。
consul須要有一個集羣,一般3~5個SERVER節點,一個CLIENT一般帶N個Service。Service到Consul能夠經過HTTP API或者是直接寫Consul配置文件的方式,CLIENT能夠認爲是無狀態的,它將註冊信息經過RPC轉發到SERVER上,服務信息保存在SERVER的各個節點上,經過Raft實現強一致性。
若是Program要訪問其餘服務器上的Service,那麼能夠經過訪問本機的CLIENT提供的HTTP API,本機CLIENT能夠將請求轉發到SERVER,SERVER查詢到Service的當前信息後返回,最終Program能夠得到Service全部的部署信息,而後就能夠向Service的其中一個部署發送請求。
consul中的agent是指節點(不管是CLIENT仍是SERVER),consul提供Script/TCP/HTTP和Interval,以及TTL等方式,可是consul的健康檢查主要是由服務註冊的Agent來處理。可是有一個壞處是,consul發現節點掛掉後,服務的狀態變爲不可用了。
Zookeeper利用臨時節點的機制,業務服務啓動時建立臨時節點,服務與節點共存亡。
etcd利用TTL機制,業務服務啓動時建立鍵值對,定時更新TTL,TTL過時服務不可用。
Zookeeper和etcd的鍵值存儲都是強一致性的,鍵值對會自動同步到多個節點,只要某個節點上存在就能夠認爲對應的業務服務是可用的。
Consul的數據同步也是強一致性的,服務的註冊信息會在SERVER節點之間同步,相比起ZK、etcd,服務信息是持久化的,即便服務部署不可用了,依然能夠查詢到這個服務部署。可是業務服務的可用狀態是由註冊到的Agent決定的,若是Agent沒法正常工做,則沒法肯定服務的真實狀態,固然,這個Agent掛掉了,其餘Agent來接管也無論用,由於Agent掛掉的話也說明這個服務器的狀態可能也不太好,此時屏蔽掉此節點啥和功能的服務也是合理的。
服務的健康檢查分爲客戶端心跳和服務端主動探測兩種方式
客戶端每隔必定時間主動發送「心跳」的方式來向服務端代表本身的服務狀態正常,心跳能夠是TCP的形式,也能夠是HTTP的形式。
維持客戶端和服務端的socket長鏈接,本身實現一個客戶端心跳。
Zookeeper沒有主動發送心跳,而是依賴組件自己提供的臨時節點的特性,經過Zookeeper鏈接的session來維持臨時節點。
可是客戶端心跳中,長鏈接的維持和客戶端的主動心跳都只是代表鏈路上的正常,不必定是服務狀態正常。
服務端調用服務發佈者某個HTTP接口來完成健康檢查。
對於沒有提供HTTP服務的RPC應用,服務端調用服務發佈者的接口來完成健康檢查。
能夠經過執行某個腳本的形式來進行綜合檢查。
可是服務端主動監測也存在問題。服務註冊中心主動調用RPC服務的某個接口沒法作到通用性;在不少場景下服務註冊中心到服務發佈者的網絡是不一樣的,服務端沒法主動發起健康檢查。
consul因爲採用了gossip機制、RPC系統、HTTPS來提供功能,這兩種系統採用的安全機制不一樣,其中gossip使用對稱密鑰提供加密,RPC則可使用客戶端認證的端到端TLS,HTTPS 也是使用客戶端認證的端到端 TLS。
此處由於本人的功力還不夠,留坑後補。
參考: