Spring cloud(2)-服務發現(Eureka,Consul)
在分散式系統領域有個著名的 CAP定理
( C-資料一致性
; A-服務可用性
; P-服務對網路分割槽故障的容錯性
,這三個特性在任何分散式系統中 不能同時滿足,最多同時滿足兩個
); eureka是AP
, zookeeper是CP
。對於 服務發現
而言, 可用性
比 資料一致性
更加重要—— AP勝過CP
Consul | zookeeper | euerka | etcd | |
---|---|---|---|---|
服務健康檢查 | 服務狀態,記憶體,硬碟等 | (弱)長連線,keepalive | 可配支援 | 連線心跳 |
多資料中心 | 支援 | — | — | — |
kv儲存服務 | 支援 | 支援 | — | 支援 |
一致性 | raft | paxos | — | raft |
CAP | ca | cp | ap | cp |
使用介面(多語言能力) | 支援http和dns | 客戶端 | http(sidecar) | http/grpc |
watch支援(客戶端觀察到服務提供者變化) | 全量/支援long polling | 支援 | 支援long polling/大部分增量 | 支援long polling |
自身監控 | metrics | — | metrics | metrics |
安全 | acl /https | acl | — | https支援(弱) |
spring cloud整合 | 已支援 | 已支援 | 已支援 | 已支援 |
-
raft
:Raft強依賴 Leader 節點的可用性來確保叢集資料的一致性。 -
paxos
: 第一次由提交者Leader向所有其他伺服器發出prepare訊息請求準備,所有伺服器中大多數如果回覆諾言承諾就表示準備好了,可以接受寫入;第二次提交者向所有伺服器發出正式建議propose,所有伺服器中大多數如果回覆已經接收就表示成功了。 -
long polling
:長輪詢,客戶端向伺服器傳送Ajax請求,伺服器接到請求後hold住連線,直到有新訊息才返回響應資訊並關閉連線,客戶端處理完響應資訊後再向伺服器傳送新的請求。 -
metrics
:作為一款監控指標的度量類庫,它提供了很多模組可以為第三方庫或者應用提供輔助統計資訊, 它還可以將度量資料傳送給Ganglia和Graphite以提供圖形化的監控 -
Eureka的自我保護模式
Eureka Server
在執行期間,會統計心跳失敗的比例在15分鐘之內是否 低於85%,如果出現低於的情況(實際在 生產環境上通常是由於網 絡不穩定導致),Eureka Server
會將當前的例項註冊資訊保護起來,同時提 示警告。保護模式主要用於一組客戶端和Eureka Server
之間存在網路分 區場景下的保護。一旦進入保護模式,Eureka Server
將會嘗試保護其服務注 冊表中的資訊,不再刪除服務登錄檔中的資料(也就是不會登出任何微服務)。所以
Eureka
的哲學是,同時保留”好資料“
與”壞資料“
總比丟掉任何”好資料“要更好,所以這種模式在實踐中非常有效。,
為啥不使用zookeeper做發現服務呢?
-
ZooKeeper
是分散式協調服務,它的職責是保證資料(注:配置資料,狀態資料)在其管轄下的所有服務之間保持同步、一致;(強一致性) - 發現服務的核心應該是需要強調服務的高可用
-
ZooKeeper
使用單一主程序Leader
用於處理客戶端所有事務請求,採用ZAB協議
將伺服器數狀態以事務形式廣播到所有Follower
上;如果三臺服務掛了兩臺怎麼選出leader
;1 不大於 (3/2)=1的
, - 正確的設定與維護
ZooKeeper服務
就非常的困難 - 叢集中出現了網路分割的故障(交換機故障導致交換機底下的子網間不能互訪)
ZooKeeper
會將它們都從自己管理範圍中剔除出去,外界就不能訪問到這些節點了,本身這些節點是“健康”
的,能提供服務的 - 發現服務就算是返回了
包含不實的資訊的結果也比什麼都不返回要好
(因為暫時的網路故障而找不到可用的伺服器)
因此, Eureka
可以很好的應對因網路故障導致部分節點失去聯絡的情況,而不會像 zookeeper
那樣使整個註冊服務癱瘓。
Spring Cloud Eureka(服務註冊)
- 新增依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> 複製程式碼
- 開啟服務註冊
通過 @EnableEurekaServer
註解啟動一個服務註冊中心提供給其他應用進行對話,這個註解需要在 springboot工程
的啟動 application類
上加
package io.ymq.example.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } 複製程式碼
Spring Cloud Service Provider(服務提供者)
- 服務提供方
- 將自身服務註冊到 Eureka 註冊中心,從而使服務消費方能夠找到
- 新增依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> 複製程式碼
-
開啟服務註冊
在應用主類中通過加上@EnableEurekaClient
,但只有Eureka
可用,你也可以使用@EnableDiscoveryClient
。需要配置才能找到Eureka註冊中心伺服器
discovery service
有許多種實現(eureka、consul、zookeeper
等)@EnableDiscoveryClient
基於spring-cloud-commons
,@EnableEurekaClient
基於spring-cloud-netflix
。就是如果選用的註冊中心是
eureka
,那麼就推薦@EnableEurekaClient
,如果是其他的註冊中心,那麼推薦使用
@EnableDiscoveryClient
。
@SpringBootApplication @EnableEurekaClient @RestController public class EurekaProviderApplication { @RequestMapping("/") public String home() { return "Hello world"; } public static void main(String[] args) { SpringApplication.run(EurekaProviderApplication.class, args); } } 複製程式碼
-
新增配置 application.yml
新增配置找到Eureka伺服器
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: eureka-provider server: port: 8081 複製程式碼
Spring Cloud Service Consumer(服務消費者)
向 Eureka
註冊服務,消費者使用 Ribbon
開啟負載均衡
Ribbon是什麼?
Ribbon
是 Netflix
釋出的開源專案,主要功能是提供客戶端的軟體負載均衡演算法,將 Netflix
的中間層服務連線在一起。 Ribbon
客戶端元件提供一系列完善的配置項如連線超時,重試等。簡單的說,就是在配置檔案中列出 Load Balancer(簡稱LB)
後面所有的機器, Ribbon
會自動的幫助你基於某種規則 (如簡單輪詢,隨即連線等)
去連線這些機器。我們也很容易使用 Ribbon
實現自定義的負載均衡演算法。
Ribbon的核心元件
Ribbon
在工作時首選會通過 ServerList
來獲取所有可用的服務列表,然後通過 ServerListFilter
過慮掉一部分地址,最後在剩下的地址中通過 IRule
選擇出一臺伺服器作為最終結果。
-
ServerList
:用於獲取地址列表。它既可以是靜態的(提供一組固定的地址),也可以是動態的(從註冊中心中定期查詢地址列表)。 -
ServerListFilter
:僅當使用動態ServerList
時使用,用於在原始的服務列表中使用一定策略過慮掉一部分地址。 -
IRule
:選擇一個最終的服務地址作為LB結果
。選擇策略有輪詢、根據響應時間加權、斷路器(當Hystrix可用時)
等。
Ribbon提供的主要負載均衡策略
-
簡單輪詢負載均衡(RoundRobin)
: 以輪詢的方式依次將請求排程不同的伺服器,即每次排程執行i = (i + 1) mod n,並選出第i臺伺服器。 -
隨機負載均衡 (Random)
: 隨機選擇狀態為UP的Server -
加權響應時間負載均衡 (WeightedResponseTime)
: 根據相應時間分配一個weight,相應時間越長,weight越小,被選中的可能性越低。 -
區域感知輪詢負載均衡(ZoneAvoidanceRule)
:複合判斷server所在區域的效能和server的可用性選擇server
服務提供者(提供服務)
- 開啟服務註冊 註冊三臺
@SpringBootApplication @EnableEurekaClient @RestController public class EurekaProviderApplication { @Value("${server.port}") String port; @RequestMapping("/") public String home() { return "Hello world ,port:" + port; } public static void main(String[] args) { SpringApplication.run(EurekaProviderApplication.class, args); } } 複製程式碼
-
新增配置 application.yml
埠依次為8081,8082,8083
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: eureka-provider server: port: 8081 複製程式碼
服務消費者(依賴於其它服務)
- pom.xml新增依賴
<!-- 客戶端負載均衡 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <!-- eureka客戶端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> 複製程式碼
-
開啟服務負載均衡
通過@EnableDiscoveryClient向服務註冊中心註冊;並且向程式的ioc注入一個bean: restTemplate並通過@LoadBalanced註解表明這個restRemplate開啟負載均衡的功能
@EnableDiscoveryClient @SpringBootApplication public class RibbonConsumerApplication { @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonConsumerApplication.class, args); } } 複製程式碼
- 消費提供者方法
/** * 描述:呼叫提供者的 `home` 方法 **/ @RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/hello") public String hello() { return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody(); } } 複製程式碼
-
新增配置 application.yml
指定服務的註冊中心地址,配置自己的服務埠,服務名稱
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: ribbon-consumer server: port: 9000 複製程式碼
依次啟動服務 (Eureka服務,三臺service provider和service Consumer)
,檢視 ribbon
是否開啟負載均衡
Spring Cloud Consul(針對Consul的服務治理實現)
由於 Consul
自身提供了服務端,所以我們不需要像之前 實現Eureka
的時候建立服務註冊中心,直接通過 ofollow,noindex">下載consul的服務端程式 就可以使用。 Consul
內建了 服務註冊
與 發現框架
(一站式)、具有以下性質(參考上面列表):
- 分佈一致性協議實現
- 健康檢查
- Key/Value儲存
- 多資料中心方案
Consul的優勢
- 使用 Raft 演算法來保證一致性, 比複雜的 Paxos 演算法更直接
- 支援多資料中心,內外網的服務採用不同的埠進行監聽
- 多資料中心叢集可以避免單資料中心的單點故障,而其部署則需要考慮網路延遲, 分片等情況等
- 支援健康檢查
- 支援 http 和 dns 協議介面
- 官方提供web管理介面
Consul的角色
-
client
:客戶端, 無狀態, 將 HTTP 和 DNS 介面請求轉發給區域網內的服務端叢集,所有註冊到當前節點的服務會被轉發到server,本身是不持久化這些資訊 -
server
:服務端, 儲存配置資訊, 高可用叢集, 在區域網內與本地客戶端通訊,功能和client都一樣,唯一不同的是,它會把所有的資訊持久化的本地,這樣遇到故障,資訊是可以被保留的。 通過廣域網與其他資料中心通訊. 每個資料中心的 server 數量推薦為 3 個或是 5 個. -
server-leader
:表明這個server是它們的老大,它和其它server不一樣的一點是,它需要負責同步註冊的資訊給其它的server,同時也要負責各個節點的健康監測。 -
raft
:server節點之間的資料一致性保證,一致性協議使用的是raft,而zookeeper用的paxos,etcd採用的也是taft。 -
服務發現協議
:consul採用http和dns協議,etcd只支援http -
服務註冊
:支援兩種方式實現服務註冊,consul官方建議使用第二種方式。
- 一種是通過consul的服務註冊http API,由服務自己呼叫API實現註冊,
- 另一種方式是通過json個是的配置檔案實現註冊,將需要註冊的服務以json格式的配置檔案給出。
-
服務發現
:支援兩種方式實現服務發現,
- 一種是通過http API來查詢有哪些服務,
- 另外一種是通過consul agent 自帶的DNS(8600埠),域名是以NAME.service.consul的形式給出,NAME即在定義的服務配置檔案中,服務的名稱。DNS方式可以通過check的方式檢查服務。
- 服務間的通訊協議:Consul使用gossip協議管理成員關係、廣播訊息到整個叢集
結語
關於 consul
的環境搭建以及應用後續再補充吧~
在 github
上有關於 Spring Cloud
完整的部署。
最後, 給個 star 吧 ~
個人部落格 ~
簡書 ~