輕松構建微服務之服務注冊和發現


微信公眾號:內核小王子
關注可了解更多關於數據庫,JVM內核相關的知識;
如果你有任何疑問也可以加我pigpdong[^1]

前言

為什么需要服務注冊中心? 隨着服務數量的擴張,我們需要服務調用方能夠自動感知到服務提供方的地址,當我們對服務提供方進行橫向擴展的時候,服務調用方能夠自動感知到,這就需要服務提供方能夠在啟動或者關閉的時候自動向注冊中心注冊,而服務調用方直接詢問注冊中心就可以知道具體的服務提供方的地址列表,服務調用方可以自己根據特定的路由算法做負載均衡, 或者服務調用方根本不需要知道服務提供方的具體地址,統一發給一個代理系統,由這個代理系統轉發給對應的服務調用方。所以為了支持服務的彈性擴展,我們需要一個獨立系統做服務發現和負載均衡,目前做服務發現有三種代理模式

集中代理模式

集中代理模式一般是在服務調用方和服務提供方之間部署一套獨立的代理系統來接收調用方的請求,然后配合域名系統和特定的負載均衡策略以及路由算法,轉發到對應的服務提供方,這個代理系統一般由硬件F5設備加7層軟件負載nginx配合域名系統來使用,這種模式,有集中治理,運維簡單,而且和語言棧無關的優點,但是目前這個代理系統存在單點問題,而且配置比較麻煩,由於服務調用者沒有之間調用服務提供方,所以網絡上存在多一跳的開銷,目前國內主要有攜程等公司在使用

image

客戶端嵌入式代理

目前很多公司用springcloud或者dubbo作為rpc框架的公司多選擇這種模式,在客戶端嵌入一個程序做服務發現和軟件負載均衡,調用方會緩存服務提供方的地址列表,並且自己根據路由算法和負載均衡策略選擇服務提供者進行調用,這種模式需要一個第三方的注冊中心配合,服務提供者啟動的時候將服務注冊到注冊中心,服務調用方去注冊中心獲取服務提供者信息,這種模式有無單點問題,性能好的優點,但是由於客戶端需要關心負載均衡和維護提供者列表,導致客戶端臃腫,目前國內主要有阿里的dubbo和新浪的Motan

image

主機獨立進程代理

這種模式是前面兩種模式的一個折中,將這個代理放到主機的一個獨立程序上,所有這個主機上的應用共享這個代理,應用一般部署在docker容器中,主機可以是一個物理機也可以是虛擬機。在這個代理上進行路由和負載均衡,這個模式也需要一個模式二中獨立的注冊中心來輔助代理程序做服務發現,這種模式兼具上面兩種模式的優點,但是運維較復雜,目前國內只有唯品會有這種模式的探索

image

servicemesh介紹

邊車模式,sidecar,將一個單獨的進程用來處理,日志,健康,限流,服務發現等功能,和應用層完全分離,目前如果我們大多lib等軟件包的形式和應用集成來實現限流和監控,這樣增加了應用依賴,每次lIB包升級都需要將應用重新編譯發布,而邊車模式下我們可以將邏輯層和控制層分開部署.

邊車模式進化后,將這個獨立程序集群化,就成了servicemesh,也就是CNCF所推薦的新一代微服務架構,將這個代理程序下沉為一個基礎服務,作為平台開放給應用程序

image

servicemesh的定義:一作為個輕量級的網絡代理專職處理服務和服務間的通訊,對應用程序透明,用來分離或者解耦和分布式系統架構中控制層的上的東西.

類似於網絡七層模型中的TCP協議,將底層那些難控制的網絡通訊方面的東西(擁塞控制,丟包重傳,流量控制)都處理了,而上層的http協議就只用關心應用層的html格式

演化路徑

  • 1.一開始最原始的兩台主機之間進程直接通訊
  • 2.然后分離出網絡層來,服務間的遠程通信通過底層的網絡模型
  • 3.由於兩邊服務由於接收速度不一致,需要在應用層做流控
  • 4.然后流控模塊交給網絡層去處理,最后TCP演化成為世界上最成功的網絡協議
  • 5.類比分布式架構中,我們在應用層加入了限流,熔斷,監控,服務發現等功能
  • 6.然后我們發現這些控制層的功能都可以標准化,我們將這些功能分別做成LIB嵌入到應用中,這樣誰需要這個功能只要加入這個LIB就好了
  • 7.最后我們發現這些LIB不能跨編程語言,然后有什么改動就需要重新編譯發布服務,不太方便,應該有一個專門的層來干這個,就是sidecar
  • 8.然后sidecar集群就成了Service mesh ,成為了一個基礎設施

image

目前開源的servicemesh實現有istio

為什么zookeeper不適合做服務發現

  • 首先我們分析下服務發現是滿足cap里面的ap還是cp

注冊中心提供了兩個服務,一個是讓服務提供方注冊,就是寫數據,另一個是讓服務調用方查詢,就是讀數據,當注冊中心集群部署后,每個節點
都可以對外提供讀寫服務,每一次寫請求都會同步到其他節點,這樣才能讓其他節點提供的讀服務正確,如果節點之間的數據復制出現不一致,那么將導致服務調用方獲取到的服務提供者列表中要么出現已經下線的節點,要么少提供了一個正常的節點,
提供了下線的節點,服務調用者可以通過重試機制調用其他節點,出現少提供一個正常節點則導致服務提供方的流量不均勻,這些都是可以接受的,何況各個節點最終都會同步成功,也就是數據最終一致性,所以我們希望注冊中心是高可用的,最好能滿足最終一致性,而zookeeper是典型的CP設計,在網絡分區情況下不可用,當節點超過半數掛掉不可用,違背了注冊中心不能因為自身任何原因破壞服務本身的可連通性

  • 另外我們分析下出現網絡分區的情況

我們看下下圖zookeeper三機房5節點部署的情況下,如果機房3和機房1機房2網絡出現分區成為孤島,zookeeper和機房3里的其他應用不能和外部通信,zookeeper由於聯系不是leader將不可用,雖然zookeeper整個集群中其他4個節點依然可以對外提供服務,但是zookeeper為了保證在腦裂的情況下數據一致性,機房3的節點5將不能進行讀寫服務,這個時候機房3內的應用A雖然不能
調用其他機房的服務B但是可以調用機房3內的服務B,但是由於Zookeeper5不能讀寫,所以機房內也不能讀寫,這對應用來說是完全不能接受的,我們有時候為了性能考慮還好主動修改路由策略讓應用盡量同機房調用,試想一下如果三個機房都出現網絡分區相互成為孤島,那么整個應用將不可用

[圖片上傳失敗...(image-269105-1558422945065)]

  • zookeeper的寫服務並不支持水平擴展

zookeeper需要和所有的服務保持長連接,而隨着服務的頻繁發布,以及服務的健康檢查,會導致zookeeper壓力越來越大,而zookeeper並不能通過橫向擴展節點解決,可以提供的方案是按照業務進行拆分到不同的zookeeper集群

  • 健康檢查

服務提供方是否可用,不能僅僅通過zookeeper的session是否存活判斷,TCP活性並不能反映服務的真實健康狀態,而需要完整的健康體系,CPU,內存,服務是否可用,數據庫是否能聯通等

幾個注冊中心的對比

指標 Consule zookeeper etcd eureka
服務監控檢測 服務狀態,內存,硬盤 長連接keepalived 連接心跳 需要配置
多數據中心 支持 不支持 不支持 不支持
KV存儲 支持 支持 支持 不支持
一致性 gossip paxos raft
CAP CA CP CP AP
使用接口(多語言能力) 支持http和dns 客戶端 http/grpc http(sidecar)
watch支持 全量/支持long polling 支持 支持 long polling 支持 long polling/大部分增量
自身監控 metrics metrics metrics
安全 acl /https acl https支持(弱)
spring cloud集成 已支持 已支持 已支持 已支持


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM