服務發現元件記錄了(大規模)分布式系統中所有服務的資訊,其它服務可以據此找到這些服務。dns 就是一個簡單的例子。當然,複雜系統的服務發現元件要提供更多的功能,例如,服務中繼資料存儲、健康監控、多種查詢和實時更新等。
服務發現是支撐大規模 soa 的核心服務。
為什麼需要服務發現呢?
假設我們寫的代碼會調用webservice、rest api、 thrift api 的服務。在調用過程中,為了完成一次請求,代碼需要知道服務執行個體的網絡位置(ip 位址和端口)。
整個過程,對于基于雲端的、現代化的微服務應用而言,這卻是一大難題。
1.1 單體應用
假設你是項目經理或者公司的架構師,正準備組織團隊開發一款産品,類似滴滴與uber的計程車排程軟體。其中系統的核心業務有:用戶端、司機端、定位、通知、支付。
傳統的架構圖為:六邊形架構(即子產品化的單體是應用),也稱單體式應用,如下圖
單體應用的不足
這種簡單方法卻有很大的局限性。
一個簡單的應用會随着時間推移逐漸變大。在每次的疊代中,開發團隊都會面對新“故事”(需求),然後開發許多新代碼。幾年後,這個小而簡單的應用會變成了一個巨大的怪物。如果有經驗的管理者都知道,一旦你的應用變成一個又大又複雜的怪物,那開發團隊肯定很痛苦。
靈活開發和部署舉步維艱,其中最主要問題就是這個應用太複雜,以至于任何單個開發者都不可能搞懂它。
降低開發速度
不利于持續性開發
子產品互相沖突
可靠性低
重構困難
1.2微服務
随着時間的發展和項目的發展,業務團隊越來越龐大,業務越來越複雜,單體應用架構已經無法滿足項目需求,是以微服務就騰空出世了。許多公司,比如amazon、ebay,通過采用微處理結構模式解決了單體應用出現的問題。
其思路不是開發一個巨大的單體式的應用,而是将應用分解為小的、互相連接配接的微服務。
微服務架構的好處
單個服務很容易開發、了解和維護。
這種架構使得每個服務都可以有專門開發團隊來開發。
微服務架構模式是每個微服務獨立的部署。
微服務架構模式使得每個服務獨立擴充。
微服務架構的不足
微服務應用是分布式系統,由此會帶來固有的複雜性。
服務位址目錄,服務健康度,部署困難,服務依賴問題,資料庫分區問題。
如何解決微服務出現的這些問題呢?服務發現架構在這時就閃亮登場了。
常用服務發現架構consul、zookeeper及etcd比較:
zookeeper是這種類型的項目中曆史最悠久的之一,它起源于hadoop。它非常成熟、可靠,被許多大公司(youtube、ebay、雅虎等)使用。
etcd是一個采用http協定的健/值對存儲系統,它是一個分布式和功能層次配置系統,可用于建構服務發現系統。其很容易部署、安裝和使用,提供了可靠的資料持久化特性。它是安全的并且文檔也十分齊全。
consul是hashicorp公司推出的開源工具,用于實作分布式系統的服務發現與配置。與其他分布式服務注冊與發現的方案相比,consul的方案更“一站式”,内置了服務注冊與發現架構、分布一緻性協定實作、健康檢查、key/value存儲、多資料中心方案,不再需要依賴其他工具(比如zookeeper等),使用起來也較為簡單。
consul用golang實作,是以具有天然可移植性,安裝包僅包含一個可執行檔案,友善部署,與docker等輕量級容器可無縫配合。
要想利用consul提供的服務實作服務的注冊與發現,我們需要建立consul cluster。在consul方案中,每個提供服務的節點上都要部署和運作consul的client agent,所有運作consul agent節點的集合構成consul cluster。consul agent有兩種運作模式:server和client。這裡的server和client隻是consul叢集層面的區分,與搭建在cluster之上的應用服務無關。以server模式運作的consul agent節點用于維護consul叢集的狀态,官方建議每個consul cluster至少有3個或以上的運作在server mode的agent,client節點不限。
每個被注冊到consul中的node上,都部署一個consul agent,這個agent負責對本地的服務進行監控檢查,以及将查詢請求轉發給consul server。consul server負責存放、備份資料(使用raft協定保證一緻性),通常要有多台形成叢集,選舉出一個leader。查詢服務位址的時候,可以直接向consul server發起查詢,也可以通過consul agent查詢,後者将轉發給consul server。如果是多資料中心,每個資料中心部署一組consul server。跨資料中心查詢通過本資料中心的consul server進行。注意:多資料中心的時候,不同資料中心的consul server之間不會同步key-value資料。
@client
client表示consul的client模式,就是用戶端模式。是consul節點的一種模式,這種模式下,所有注冊到目前節點的服務會被轉發到server,本身是不持久化這些資訊。
@server
server表示consul的server模式,表明這個consul是個server,這種模式下,功能和client都一樣,唯一不同的是,它會把所有的資訊持久化的本地,這樣遇到故障,資訊是可以被保留的。
@server-leader
中間那個server下面有leader的字眼,表明這個server是它們的老大,它和其它server不一樣的一點是,它需要負責同步注冊的資訊給其它的server,同時也要負責各個節點的健康監測。
@raft
server節點之間的資料一緻性保證,一緻性協定使用的是raft,而zookeeper用的paxos,etcd采用的也是raft。
@服務發現協定
consul采用http和dns協定,etcd隻支援http
@服務注冊
consul支援兩種方式實作服務注冊,一種是通過consul的服務注冊http api,由服務自己調用api實作注冊,另一種方式是通過json個是的配置檔案實作注冊,将需要注冊的服務以json格式的配置檔案給出。consul官方建議使用第二種方式。
@服務發現
consul支援兩種方式實作服務發現,一種是通過http api來查詢有哪些服務,另外一種是通過consul agent 自帶的dns(8600端口),域名是以name.service.consul的形式給出,name即在定義的服務配置檔案中,服務的名稱。dns方式可以通過check的方式檢查服務。
@服務間的通信協定
consul使用gossip協定管理成員關系、廣播消息到整個叢集,他有兩個gossip pool(lan pool和wan pool),lan pool是同一個資料中心内部通信的,wan pool是多個資料中心通信的,lan pool有多個,wan pool隻有一個。
consul的三個主要應用場景:服務發現、服務隔離、服務配置。
服務發現場景中,consul作為注冊中心,服務位址被注冊到consul中以後,可以使用consul提供的dns、http接口查詢,consul支援health check。
服務隔離場景中,consul支援以服務為機關設定通路政策,能同時支援經典的平台和新興的平台,支援tls證書分發,service-to-service加密。
服務配置場景中,consul提供key-value資料存儲功能,并且能将變動迅速地通知出去,通過工具consul-template可以更友善地實時渲染配置檔案。
consul是一個二進制檔案,可獨立運作,直接從官網下載下傳解壓後儲存到/usr/local/bin下即可:https://www.consul.io/downloads.html。
consul必須啟動agent才能使用,有兩種啟動模式server和client,還有官方自帶的ui。
參數解釋:
常用指令如下:
1)information
可以在raft:stat看到此節點的狀态是fllower或者leader
2)列出叢集成員
3)新加入一個節點有幾種方式;
這種方式,重新開機後不會自動加入叢集
在啟動的時候使用-join指定一個叢集
使用-startjoin或-rejoin
4)consul預設綁定的端口
8300:server rpc address
8301:lan gossip,the serf lan port
8302:wan gossip,the serf wan port
8500:http api端口
8501:httpsapi端口,預設disabled
8502:grpcapi端口,預設disabled
8600:dns服務端口
21000:sidecar proxy min: inclusive min port number to use for automatically assigned sidecar service registrations.
21255:sidecar proxy max: inclusive max port number to use for automatically assigned sidecar service registrations.
5)健康檢查
check使用來做服務的健康檢查的,可以擁有多個,也可以不使用支援多種方式檢查。check必須是script或者ttl類型的,如果是script類型則script和interval變量必須被提供,如果是ttl類型則ttl變量必須被提供。script是consul主動去檢查服務的健康狀況,ttl是服務主動向consul報告自己的狀況。
script check:
http check:
tcp check:
ttl check:
6)服務注冊
注冊服務有三種方式。
通過配置檔案的方式靜态注冊
儲存json配置檔案到consul配置目錄,重新開機consul,并将配置檔案的路徑給consul。
通過http api接口來動态注冊
直接調用/v1/agent/service/register接口注冊即可,需要注意的是:http method為put送出方式,如:
注意:這種方式,和上面的注冊方式有一點不一樣,body的參數,是上面service的值。
使用程式實作服務的注冊和發現(java)
7)查詢服務
或者通過httpapi查詢:
查詢agent上所有服務:
8)删除服務
在一台主機上通過docker容器方式分别運作1個server和3個client,docker容器基于ubuntu:16.04,在此基礎上安裝ifconfig(net-tools),ping工具包用于基礎應用和consul,并送出為新鏡像:
然後server容器執行下列指令:
三個client容器建立指令:
三個client運作consul agent:
注:4個容器模拟4台主機,共享檔案名不可相同(否則建立錯誤),隻有server配置webui并暴露端口。
可通過此通路consul:http://192.168.134.144:8500。
在一個client上運作web服務(如cn12),web.json内容(啟動consul時check錯誤,可先去掉check):
web服務采用go,即web.go:
在cn1上運作web并重新開機consul,可在其他主機上(如cn13)運作如下指令探測到相關服務,或通過ui檢視到web service。
golang可直接通過consul庫注冊、發現服務。