服務發現的基本原理
一、什麽是服務發現
服務提供者是什麽, 簡單說就是一個HTTP服務器,提供了API服務,有一個IP端口作為服務地址。 服務消費者是什麽?
就是一個簡單的進程,想要訪問服務提供者提供的服務來做一些事情。 一個HTTP服務器既可以是服務提供者對外提供
服務,也可以是消費者需要別的服務提供者提供的服務,這就是服務依賴。復雜的服務甚至有多個服務依賴
服務發現有三個角色,服務提供者、服務消費者和服務中介。 服務中介是聯系服務提供者和服務消費者的橋梁。服務提供者
將自己提供的服務地址註冊到服務中介,服務消費者從服務中介那裏查找自己想要的服務地址,然後使用這個服務。 服務中介
提供多個服務,每個服務對應多個服務提供者。
服務中介就是一個字典,字典裏有很多key-value鍵值對,key是服務名稱,value是服務提供者的地址列表。服務註冊就是調用
字典的put方法放東西,服務查找就是調用字典的get方法獲取東西
當服務提供者新加入時,要求服務中介能及時告知服務消費者。
二、Redis作為服務中介
Redis裏面有豐富的數據結構,用來存儲服務字典很合適。 對每一個服務名稱,可以用一個set結構存儲服務的IP:port字符串
如果服務提供者加入,調用sadd命令加入服務地址,如果服務掛掉,調用srem命令移除服務地址。 對服務消費者使用smembers
指令來獲取所有服務地址然後在消費進程裏隨機調一個,或者使用srandmember命令直接獲取隨機服務地址。
如果服務提供者進程備暴力殺死了,不能主動調用srem命令怎麽處理? 這個時候服務列表中多了一個黑地址指向了不存在的服務
二消費者完全不知道,這個時候服務中介就成了黑中介了。 因此,引入服務保活和檢查機制,病更換數據結構。服務提供這需要每隔5秒
左右向服務中介匯報存活, 服務中介將付地址和匯報時間記錄在zset數據結構的value和score中。 服務中介需要每隔10秒左右檢查zset
數據結果。
那麽服務列表變動時如何通知消費者?
第一種方式是輪詢,消費者需要每隔幾秒查詢服務列表是否有改變。 如果服務很多,服務列表很大, 消費者很多,Redis會右一定壓力。
這時可以引入服務列表的版本號控制,給每個服務提供一個key/value設置服務的版本號,就是在服務列表發生變動時,遞增這個版本號。
消費者只要輪詢這個版本號的變動即可直到服務列表是否發生了變化。
第二種方式就是采用pubsub。 及時性明顯好於輪詢。缺點就是每個pubsub都會占用消費者一個線程和一個額外的Redis連接。 為了減少
對線程和連接的浪費,我們使用單個pubsub廣播全局版本號的變動。 所謂全局版本號就是任意服務列表發生了變動,這個版本號都會地藏。
接受到版本變動的消費者再去檢查各自的依賴服務列表的版本號是否發生了變動。
Redis的單點問題怎麽解決?
現流行的服務發現系統都是使用分布式數據庫zookeeper etcd consul等來作為服務中介,他們是分布式的多節點的,掛掉了一個節點沒關系
系統仍然可以正常工作。 那如果整個zk集群都掛掉? 其實每個服務消費者在本地內存裏都會存一份當前的服務列表,即使服務中介集群掛掉,
也是可以使用當前的服務列表正常工作的。 也可以Redis-sentinel可以在主節點掛掉的時候,自動升級從節點為主節點
三、服務配置重加載
服務發現一般只是用來註冊和查找服務列表這樣一個比較單純的功能。不過現代的服務發現系統還會集成服務配置管理功能。這樣可以實現服務
配置的實時重加載。 服務中介還會存儲一個單獨的key/value用來存儲這個服務的配置信息。當這個配置項在後臺被修改時,服務中介會實時通知
相關服務器變更配置信息。 比如數據庫地址變動,業務參數修改等。
四、服務管理後臺
為了便於服務管理,一般服務發現還會提供一個服務管理後臺,用於管理人員查看服務集群的狀態。如果服務註冊和匯報時提供冗余的配置信息,服務
管理後臺就可以呈現更為詳細的服務信息。服務管理後臺還可以將所有的服務依賴組織起來,形成完整的依賴。
服務發現的基本原理