服務(wù)注冊與發(fā)現(xiàn)的原理和實現(xiàn)

什么是服務(wù)注冊發(fā)現(xiàn)中贝?

對于搞微服務(wù)的同學(xué)來說啃奴,服務(wù)注冊、服務(wù)發(fā)現(xiàn)的概念應(yīng)該不會太陌生雄妥。

簡單來說最蕾,當(dāng)服務(wù)A需要依賴服務(wù)B時,我們就需要告訴服務(wù)A老厌,哪里可以調(diào)用到服務(wù)B瘟则,這就是服務(wù)注冊發(fā)現(xiàn)要解決的問題。

image
  • Service B 把自己注冊到 Service Registry 叫做 服務(wù)注冊
  • Service AService Registry 發(fā)現(xiàn) Service B 的節(jié)點信息叫做 服務(wù)發(fā)現(xiàn)

服務(wù)注冊

服務(wù)注冊是針對服務(wù)端的枝秤,服務(wù)啟動后需要注冊醋拧,分為幾個部分:

  • 啟動注冊
  • 定時續(xù)期
  • 退出撤銷

啟動注冊

當(dāng)一個服務(wù)節(jié)點起來之后,需要把自己注冊到 Service Registry 上淀弹,便于其它節(jié)點來發(fā)現(xiàn)自己丹壕。注冊需要在服務(wù)啟動完成并可以接受請求時才會去注冊自己,并且會設(shè)置有效期薇溃,防止進(jìn)程異常退出后依然被訪問菌赖。

定時續(xù)期

定時續(xù)期相當(dāng)于 keep alive,定期告訴 Service Registry 自己還在沐序,能夠繼續(xù)服務(wù)琉用。

退出撤銷

當(dāng)進(jìn)程退出時堕绩,我們應(yīng)該主動去撤銷注冊信息,便于調(diào)用方及時將請求分發(fā)到別的節(jié)點邑时。同時奴紧,go-zero 通過自適應(yīng)的負(fù)載均衡來保證即使節(jié)點退出沒有主動注銷,也能及時摘除該節(jié)點晶丘。

服務(wù)發(fā)現(xiàn)

服務(wù)發(fā)現(xiàn)是針對調(diào)用端的黍氮,一般分為兩類問題:

  • 存量獲取
  • 增量偵聽

還有一個常見的工程問題是

  • 應(yīng)對服務(wù)發(fā)現(xiàn)故障

當(dāng)服務(wù)發(fā)現(xiàn)服務(wù)(比如 etcd, consul, nacos等)出現(xiàn)問題的時候,我們不要去修改已經(jīng)獲取到的 endpoints 列表浅浮,從而可以更好的確保 etcd 等宕機后所依賴的服務(wù)依然可以正常交互滤钱。

存量獲取

image

當(dāng) Service A 啟動時,需要從 Service Registry 獲取 Service B 的已有節(jié)點列表:Service B1, Service B2, Service B3脑题,然后根據(jù)自己的負(fù)載均衡算法來選擇合適的節(jié)點發(fā)送請求。

增量偵聽

上圖已經(jīng)有了 Service B1, Service B2, Service B3铜靶,如果此時又啟動了 Service B4叔遂,那么我們就需要通知 Service A 有個新增的節(jié)點。如圖:

image

應(yīng)對服務(wù)發(fā)現(xiàn)故障

對于服務(wù)調(diào)用方來說争剿,我們都會在內(nèi)存里緩存一個可用節(jié)點列表已艰。不管是使用 etcdconsul 或者 nacos 等蚕苇,我們都可能面臨服務(wù)發(fā)現(xiàn)集群故障哩掺,以 etcd 為例,當(dāng)遇到 etcd 故障時涩笤,我們就需要凍結(jié) Service B 的節(jié)點信息而不去變更嚼吞,此時一定不能去清空節(jié)點信息,一旦清空就無法獲取了蹬碧,而此時 Service B 的節(jié)點很可能都是正常的舱禽,并且 go-zero 會自動隔離和恢復(fù)故障節(jié)點。

image

服務(wù)注冊恩沽、服務(wù)發(fā)現(xiàn)的基本原理大致如此誊稚,當(dāng)然實現(xiàn)起來還是比較復(fù)雜的,接下來我們一起看看 go-zero 里支持哪些服務(wù)發(fā)現(xiàn)的方式罗心。

go-zero 之內(nèi)置服務(wù)發(fā)現(xiàn)

go-zero 默認(rèn)支持三種服務(wù)發(fā)現(xiàn)方式:

  • 直連
  • 基于 etcd 的服務(wù)發(fā)現(xiàn)
  • 基于 kubernetes endpoints 的服務(wù)發(fā)現(xiàn)

直連

直連是最簡單的方式里伯,當(dāng)我們的服務(wù)足夠簡單時,比如單機即可承載我們的業(yè)務(wù)渤闷,我們可以直接只用這種方式疾瓮。

image

rpc 的配置文件里直接指定 endpoints 即可,比如:

Rpc:
  Endpoints:
  - 192.168.0.111:3456
  - 192.168.0.112:3456

zrpc 調(diào)用端就會分配負(fù)載到這兩個節(jié)點上飒箭,其中一個節(jié)點有問題時 zrpc 會自動摘除爷贫,等節(jié)點恢復(fù)時會再次分配負(fù)載认然。

這個方法的缺點是不能動態(tài)增加節(jié)點,每次新增節(jié)點都需要修改調(diào)用方配置并重啟漫萄。

基于 etcd 的服務(wù)發(fā)現(xiàn)

當(dāng)我們的服務(wù)有一定規(guī)模之后卷员,因為一個服務(wù)可能會被很多個服務(wù)依賴,我們就需要能夠動態(tài)增減節(jié)點腾务,而無需修改很多的調(diào)用方配置并重啟毕骡。

常見的服務(wù)發(fā)現(xiàn)方案有 etcd, consul, nacos 等。

image

go-zero內(nèi)置集成了基于 etcd 的服務(wù)發(fā)現(xiàn)方案岩瘦,具體使用方法如下:

Rpc:
  Etcd:
     Hosts:
     - 192.168.0.111:2379
     - 192.168.0.112:2379
     - 192.168.0.113:2379
     Key: user.rpc
  • Hostsetcd 集群地址
  • Key 是服務(wù)注冊上去的 key

基于 Kubernetes Endpoints 的服務(wù)發(fā)現(xiàn)

如果我們的服務(wù)都是部署在 Kubernetes 集群上的話未巫,Kubernetes 本身是通過自帶的 etcd 管理集群狀態(tài)的,所有的服務(wù)都會把自己的節(jié)點信息注冊到 Endpoints 對象启昧,我們可以直接給 deployment 權(quán)限去讀取集群的 Endpoints 對象即可獲得節(jié)點信息叙凡。

image
  • Service B 的每個 Pod 啟動時,會將自己注冊到集群的 Endpoints
  • Service A 的每個 Pod 啟動時密末,可以從集群的 Endpoints 里獲取 Service B 的節(jié)點信息
  • 當(dāng) Service B 的節(jié)點發(fā)生改變時握爷,Service A 可以通過 watch 集群的 Endpoints 感知到

在這個機制工作之前,我們需要配置好當(dāng)前 namespace 內(nèi) pod 對集群 Endpoints 訪問權(quán)限严里,這里有三個概念:

  • ClusterRole
    • 定義集群范圍的權(quán)限角色新啼,不受 namespace 控制
  • ServiceAccount
    • 定義 namespace 范圍內(nèi)的 service account
  • ClusterRoleBinding
    • 將定義好的 ClusterRole 和不同 namespaceServiceAccount 進(jìn)行綁定

具體的 Kubernetes 配置文件可以參考 這里,其中 namespace 按需修改刹碾。

注意:當(dāng)啟動時報沒有權(quán)限獲取 Endpoints 時記得檢查這些配置有沒落實 :)

zrpc 的基于 Kubernetes Endpoints 的服務(wù)發(fā)現(xiàn)使用方法如下:

Rpc:
  Target: k8s://mynamespace/myservice:3456

其中:

  • mynamespace:被調(diào)用的 rpc 服務(wù)所在的 namespace
  • myservice:被調(diào)用的 rpc 服務(wù)的名字
  • 3456:被調(diào)用的 rpc 服務(wù)的端口

在創(chuàng)建 deployment 配置文件時一定要加上 serviceAccountName 來指定使用哪個 ServiceAccount燥撞,示例如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: alpine-deployment
  labels:
    app: alpine
spec:
  replicas: 1
  selector:
    matchLabels:
      app: alpine
  template:
    metadata:
      labels:
        app: alpine
    spec:
      serviceAccountName: endpoints-reader
      containers:
      - name: alpine
        image: alpine
        command:
        - sleep
        - infinity

注意其中 serviceAccountName 指定該 deployment 創(chuàng)建出來的 pod 用哪個 ServiceAccount

serverclient 都部署到 Kubernetes 集群里之后可以通過以下命令滾動重啟所有 server 節(jié)點

kubectl rollout restart deploy -n adhoc server-deployment

利用如下命令查看 client 節(jié)點日志:

kubectl -n adhoc logs -f deploy/client-deployment --all-containers=true

可以看到我們的服務(wù)發(fā)現(xiàn)機制完美跟進(jìn)了 server 節(jié)點的變化迷帜,并且在服務(wù)更新期間沒有出現(xiàn)異常請求物舒。

完整代碼示例見 https://github.com/zeromicro/zero-examples/tree/main/discovery/k8s

下一篇文章我將講解在 go-zero 里如何實現(xiàn)基于 consul, nacos 等的服務(wù)注冊發(fā)現(xiàn),敬請期待戏锹!

項目地址

https://github.com/tal-tech/go-zero

歡迎使用 go-zerostar 支持我們茶鉴!

微信交流群

關(guān)注『微服務(wù)實踐』公眾號并點擊 交流群 獲取社區(qū)群二維碼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末景用,一起剝皮案震驚了整個濱河市涵叮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伞插,老刑警劉巖割粮,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異媚污,居然都是意外死亡舀瓢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門耗美,熙熙樓的掌柜王于貴愁眉苦臉地迎上來京髓,“玉大人航缀,你說我怎么就攤上這事⊙咴梗” “怎么了芥玉?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長备图。 經(jīng)常有香客問我灿巧,道長,這世上最難降的妖魔是什么揽涮? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任抠藕,我火速辦了婚禮,結(jié)果婚禮上蒋困,老公的妹妹穿的比我還像新娘盾似。我一直安慰自己,他們只是感情好雪标,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布零院。 她就那樣靜靜地躺著,像睡著了一般汰聋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喊积,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天烹困,我揣著相機與錄音,去河邊找鬼乾吻。 笑死髓梅,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绎签。 我是一名探鬼主播枯饿,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诡必!你這毒婦竟也來了奢方?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤爸舒,失蹤者是張志新(化名)和其女友劉穎蟋字,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扭勉,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡鹊奖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了涂炎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忠聚。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡设哗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出两蟀,到底是詐尸還是另有隱情网梢,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布垫竞,位于F島的核電站澎粟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏欢瞪。R本人自食惡果不足惜活烙,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望遣鼓。 院中可真熱鬧啸盏,春花似錦、人聲如沸骑祟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽次企。三九已至怯晕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缸棵,已是汗流浹背舟茶。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留堵第,地道東北人吧凉。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像踏志,于是被迫代替她去往敵國和親阀捅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容