您好,登錄后才能下訂單哦!
本篇內容主要講解“什么是服務發現以及Redis作為服務中介的介紹”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“什么是服務發現以及Redis作為服務中介的介紹”吧!
什么是服務發現?
服務發現并沒有怎樣的高深莫測,它的原理再簡單不過。
服務提供者是什么,簡單點說就是一個HTTP服務器,提供了API服務,有一個IP端口作為服務地址。服務消費者是什么,它就是一個簡單的進程,想要訪問服務提供者提供的服務來干一些事情。一個HTTP服務器既可以是服務提供者對外提供服務,也可以是消費者需要別的服務提供者提供的服務,這就是服務依賴,沒有你我就不是我自己。復雜的服務甚至有多個服務依賴。
服務發現有三個角色,服務提供者、服務消費者和服務中介。服務中介是聯系服務提供者和服務消費者的橋梁。服務提供者將自己提供的服務地址注冊到服務中介,服務消費者從服務中介那里查找自己想要的服務的地址,然后享受這個服務。服務中介提供多個服務,每個服務對應多個服務提供者。
image
服務中介就是一個字典,字典里有很多key/value鍵值對,key是服務名稱,value是服務提供者的地址列表。服務注冊就是調用字典的Put方法塞東西,服務查找就是調用字典的Get方法拿東西。
當服務提供者節點掛掉時,要求服務能夠及時取消注冊,比便及時通知消費者重新獲取服務地址。
當服務提供者新加入時,要求服務中介能及時告知服務消費者,你要不要嘗試一下新的服務。
Redis作為服務中介
Redis里面有豐富的數據結構,拿來存儲服務字典再合適不過了。對每一個服務名稱,我們用一個set結構存儲服務的IP:Port字符串。如果服務提供者加入,調用sadd命令加入服務地址,如果服務掛掉,調用srem命令移除服務地址。對服務消費者使用smembers指令獲取所有服務地址然后在消費進程里隨機挑一個,或者使用srandmemember指令直接獲取隨機服務地址。
這個時候你也許會表示懷疑,服務發現真這么簡單么?答案是還差一點,關于上面的這個解決方案有幾個問題。
第一個問題是服務提供者進程如果被kill -9暴力殺死,不能主動調用srem命令怎么辦?
這個時候服務列表中多了一個黑地址指向了不存在的服務而消費者完全不知道,這個時候服務中介就成了黑中介了。那該怎么辦呢?
我們引入服務保活和檢查機制,并更換數據結構。服務提供者需要每隔5秒左右向服務中介匯報存活,服務中介將服務地址和匯報時間記錄在zset數據結構的value和score中。服務中介需要每隔10秒左右檢查zset數據結構,踢掉匯報時間嚴重落后的服務地址項。這樣就可以準實時地保證服務列表中服務地址的有效性。
第二個問題是服務列表變動時如何通知消費者。有兩種解決方案。
第一種是輪詢,消費者需要每隔幾秒查詢服務列表是否有改變。如果服務很多,服務列表很大,消費者很多,redis會有一定壓力。所以這時候可以引入服務列表的版本號機制,給每個服務提供一個key/value設置服務的版本號,就是在服務列表發生變動時,遞增這個版本號。消費者只需要輪詢這個版本號的變動即可知道服務列表是否發生了變化。因為服務列表比較穩定,僅在網絡嚴重抖動的情況下才會頻繁發生變動,所以redis幾乎沒有壓力。
第二種是采用pubsub。這種方式及時性要明顯好于輪詢。缺點是每個pubsub都會占用消費者一個線程和一個額外的redis連接。為了減少對線程和連接的浪費,我們使用單個pubsub廣播全局版本號的變動。所謂全局版本號就是任意服務列表發生了變動,這個版本號都會遞增。接收到版本變動的消費者再去檢查各自的依賴服務列表的版本號是否發生了變動。這種全局版本號也可以用于第一種輪詢方案。
第三個問題是redis是單點的,如果掛掉了怎么辦?
這是個大問題。正是因為這個問題的存在,流行的服務發現系統都是使用分布式數據庫zookeeper/etcd/consul等來作為服務中介,它們是分布式的多節點的,掛掉了一個節點沒關系,系統仍然可以正常工作。
image
那如果整個zk集群掛掉會怎樣呢?其實每個服務消費者在本地內存里都會存一份當前的服務列表,即使服務中介集群掛掉,也是可以使用當前的服務列表正常工作的。
那redis作為服務中介就真的不靠譜了么?其實還有個redis-sentinel可以消除redis的單點問題,redis-sentinel可以在主節點掛掉的時候,自動升級從節點為主節點。所以拿redis干這件事也是可以的。用redis干服務發現確實非常簡單,雖然這種方式非常不流行。
服務提供者不只是HTTP服務
上面提到服務提供者簡單來說就是HTTP服務器,其實服務多種多樣。可以是數據庫服務,可以是RPC服務,可以是UDP服務等等。
如果是MySQL數據庫,那如何將MySQL服務注冊到服務中介呢?原生的MySQL可沒有提供這樣功能。一般做法是提供一個Agent代理去注冊。這個代理除了將服務地址注冊到服務中介外,還需要監控MySQL的健康狀況,以便當MySQL宕機時能及時切換到新的MySQL服務地址。一般這個Agent為了節省資源而不止監控一個數據庫,它可以同時監控多個數據庫,甚至是多種數據庫。
服務配置重加載
服務發現一般只是用來注冊和查找服務列表這樣一個比較單純的功能。不過現代的服務發現系統還會集成服務配置管理功能。這樣可以實現服務配置的實時重加載。原理也很簡單,就是對于每一個服務項,服務中介還會存儲一個單獨的key/value用來存儲這個服務的配置信息。當這個配置項在后臺被修改時,服務中介會實時通知相關服務器變更配置信息。比如數據庫地址變動,業務參數修改等。
服務管理后臺
為了便于服務管理,一般服務發現還會提供一個服務管理后臺,用于管理人員查看服務集群的狀態。如果服務注冊和匯報時提供冗余的配置信息,服務管理后臺就可以呈現更為詳細的服務信息。服務管理后臺還可以將所有的服務依賴組織起來,呈現出一顆漂亮的服務依賴樹。
服務發現的一個簡單實現
小編在閑暇之余基于Redis實現了一個簡單的服務發現系統Captain。讀者可以去github上下載這個項目進行學習。我除了編寫了服務發現的服務器之外,客戶端sdk也一塊做了開發,可能不太穩定,希望讀者體諒,不要用于線上的業務系統。
在Captain這個項目里,我的服務發現服務器將Redis提供的服務做了一層封裝,對外提供HTTP API進行服務的注冊和查找,沒有使用上文提到的pubsub功能。
到此,相信大家對“什么是服務發現以及Redis作為服務中介的介紹”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。