在分布式系統(tǒng)領(lǐng)域有個著名的CAP定理
(C-數(shù)據(jù)一致性
蝗锥;A-服務可用性
;P-服務對網(wǎng)絡分區(qū)故障的容錯性
率触,這三個特性在任何分布式系統(tǒng)中不能同時滿足终议,最多同時滿足兩個
);
eureka是AP
,zookeeper是CP
葱蝗。對于服務發(fā)現(xiàn)
而言穴张,可用性
比數(shù)據(jù)一致性
更加重要——AP勝過CP
Consul | zookeeper | euerka | etcd | |
---|---|---|---|---|
服務健康檢查 | 服務狀態(tài),內(nèi)存两曼,硬盤等 | (弱)長連接皂甘,keepalive | 可配支持 | 連接心跳 |
多數(shù)據(jù)中心 | 支持 | — | — | — |
kv存儲服務 | 支持 | 支持 | — | 支持 |
一致性 | raft | paxos | — | raft |
CAP | ca | cp | ap | cp |
使用接口(多語言能力) | 支持http和dns | 客戶端 | http(sidecar) | http/grpc |
watch支持(客戶端觀察到服務提供者變化) | 全量/支持long polling | 支持 | 支持long polling/大部分增量 | 支持long polling |
自身監(jiān)控 | metrics | — | metrics | metrics |
安全 | acl /https | acl | — | https支持(弱) |
spring cloud集成 | 已支持 | 已支持 | 已支持 | 已支持 |
-
raft
:Raft強依賴 Leader 節(jié)點的可用性來確保集群數(shù)據(jù)的一致性。
paxos
: 第一次由提交者Leader向所有其他服務器發(fā)出prepare消息請求準備悼凑,所有服務器中大多數(shù)如果回復諾言承諾就表示準備好了偿枕,可以接受寫入;第二次提交者向所有服務器發(fā)出正式建議propose户辫,所有服務器中大多數(shù)如果回復已經(jīng)接收就表示成功了渐夸。long polling
:長輪詢,客戶端向服務器發(fā)送Ajax請求渔欢,服務器接到請求后hold住連接墓塌,直到有新消息才返回響應信息并關(guān)閉連接,客戶端處理完響應信息后再向服務器發(fā)送新的請求奥额。metrics
:作為一款監(jiān)控指標的度量類庫苫幢,它提供了很多模塊可以為第三方庫或者應用提供輔助統(tǒng)計信息, 它還可以將度量數(shù)據(jù)發(fā)送給Ganglia和Graphite以提供圖形化的監(jiān)控Eureka的自我保護模式
Eureka Server
在運行期間垫挨,會統(tǒng)計心跳失敗的比例在15分鐘之內(nèi)是否
低于85%态坦,如果出現(xiàn)低于的情況(實際在
生產(chǎn)環(huán)境上通常是由于網(wǎng)
絡不穩(wěn)定導致),Eureka Server
會將當前的實例注冊信息保護起來棒拂,同時提
示警告伞梯。保護模式主要用于一組客戶端和Eureka Server
之間存在網(wǎng)絡分
區(qū)場景下的保護玫氢。一旦進入保護模式,Eureka Server
將會嘗試保護其服務注
冊表中的信息谜诫,不再刪除服務注冊表中的數(shù)據(jù)(也就是不會注銷任何微服務)漾峡。
所以Eureka
的哲學是,同時保留”好數(shù)據(jù)“
與”壞數(shù)據(jù)“
總比丟掉任何”好數(shù)據(jù)“要更好喻旷,所以這種模式在實踐中非常有效生逸。,
為啥不使用zookeeper做發(fā)現(xiàn)服務呢且预?
-
ZooKeeper
是分布式協(xié)調(diào)服務槽袄,它的職責是保證數(shù)據(jù)(注:配置數(shù)據(jù),狀態(tài)數(shù)據(jù))在其管轄下的所有服務之間保持同步锋谐、一致遍尺;(強一致性) - 發(fā)現(xiàn)服務的核心應該是需要強調(diào)服務的高可用
-
ZooKeeper
使用單一主進程Leader
用于處理客戶端所有事務請求,采用ZAB協(xié)議
將服務器數(shù)狀態(tài)以事務形式廣播到所有Follower
上涮拗;如果三臺服務掛了兩臺怎么選出leader
乾戏;1 不大于 (3/2)=1的
, - 正確的設置與維護
ZooKeeper服務
就非常的困難 - 集群中出現(xiàn)了網(wǎng)絡分割的故障(交換機故障導致交換機底下的子網(wǎng)間不能互訪)
ZooKeeper
會將它們都從自己管理范圍中剔除出去三热,外界就不能訪問到這些節(jié)點了鼓择,本身這些節(jié)點是“健康”
的,能提供服務的 - 發(fā)現(xiàn)服務就算是返回了
包含不實的信息的結(jié)果也比什么都不返回要好
(因為暫時的網(wǎng)絡故障而找不到可用的服務器)
因此就漾, Eureka
可以很好的應對因網(wǎng)絡故障導致部分節(jié)點失去聯(lián)系的情況呐能,而不會像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
有許多種實現(xiàn)(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
發(fā)布的開源項目,主要功能是提供客戶端的軟件負載均衡算法节芥,將Netflix
的中間層服務連接在一起在刺。Ribbon
客戶端組件提供一系列完善的配置項如連接超時逆害,重試等。簡單的說蚣驼,就是在配置文件中列出Load Balancer(簡稱LB)
后面所有的機器魄幕,Ribbon
會自動的幫助你基于某種規(guī)則(如簡單輪詢,隨即連接等)
去連接這些機器颖杏。我們也很容易使用Ribbon
實現(xiàn)自定義的負載均衡算法纯陨。
Ribbon的核心組件
Ribbon
在工作時首選會通過ServerList
來獲取所有可用的服務列表,然后通過ServerListFilter
過慮掉一部分地址留储,最后在剩下的地址中通過IRule
選擇出一臺服務器作為最終結(jié)果翼抠。
-
ServerList
:用于獲取地址列表。它既可以是靜態(tài)的(提供一組固定的地址)获讳,也可以是動態(tài)的(從注冊中心中定期查詢地址列表)阴颖。 -
ServerListFilter
:僅當使用動態(tài)ServerList
時使用,用于在原始的服務列表中使用一定策略過慮掉一部分地址赔嚎。 -
IRule
:選擇一個最終的服務地址作為LB結(jié)果
膘盖。選擇策略有輪詢、根據(jù)響應時間加權(quán)尤误、斷路器(當Hystrix可用時)
等侠畔。
Ribbon提供的主要負載均衡策略
-
簡單輪詢負載均衡(RoundRobin)
: 以輪詢的方式依次將請求調(diào)度不同的服務器,即每次調(diào)度執(zhí)行i = (i + 1) mod n损晤,并選出第i臺服務器软棺。 -
隨機負載均衡 (Random)
: 隨機選擇狀態(tài)為UP的Server -
加權(quán)響應時間負載均衡 (WeightedResponseTime)
: 根據(jù)相應時間分配一個weight,相應時間越長尤勋,weight越小喘落,被選中的可能性越低。 -
區(qū)域感知輪詢負載均衡(ZoneAvoidanceRule)
:復合判斷server所在區(qū)域的性能和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);
}
}
- 消費提供者方法
/**
* 描述:調(diào)用提供者的 `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的服務治理實現(xiàn))
由于Consul
自身提供了服務端,所以我們不需要像之前實現(xiàn)Eureka
的時候創(chuàng)建服務注冊中心篇裁,直接通過下載consul的服務端程序就可以使用沛慢。
Consul
內(nèi)置了服務注冊
與發(fā)現(xiàn)框架
(一站式)、具有以下性質(zhì)(參考上面列表):
- 分布一致性協(xié)議實現(xiàn)
- 健康檢查
- Key/Value存儲
- 多數(shù)據(jù)中心方案
Consul的優(yōu)勢
- 使用 Raft 算法來保證一致性, 比復雜的 Paxos 算法更直接
- 支持多數(shù)據(jù)中心达布,內(nèi)外網(wǎng)的服務采用不同的端口進行監(jiān)聽
- 多數(shù)據(jù)中心集群可以避免單數(shù)據(jù)中心的單點故障,而其部署則需要考慮網(wǎng)絡延遲, 分片等情況等
- 支持健康檢查
- 支持 http 和 dns 協(xié)議接口
- 官方提供web管理界面
Consul的角色
-
client
:客戶端, 無狀態(tài), 將 HTTP 和 DNS 接口請求轉(zhuǎn)發(fā)給局域網(wǎng)內(nèi)的服務端集群团甲,所有注冊到當前節(jié)點的服務會被轉(zhuǎn)發(fā)到server,本身是不持久化這些信息 -
server
:服務端, 保存配置信息, 高可用集群, 在局域網(wǎng)內(nèi)與本地客戶端通訊,功能和client都一樣黍聂,唯一不同的是躺苦,它會把所有的信息持久化的本地身腻,這樣遇到故障,信息是可以被保留的圾另。 通過廣域網(wǎng)與其他數(shù)據(jù)中心通訊. 每個數(shù)據(jù)中心的 server 數(shù)量推薦為 3 個或是 5 個. -
server-leader
:表明這個server是它們的老大霸株,它和其它server不一樣的一點是,它需要負責同步注冊的信息給其它的server集乔,同時也要負責各個節(jié)點的健康監(jiān)測去件。 -
raft
:server節(jié)點之間的數(shù)據(jù)一致性保證,一致性協(xié)議使用的是raft扰路,而zookeeper用的paxos尤溜,etcd采用的也是taft。 -
服務發(fā)現(xiàn)協(xié)議
:consul采用http和dns協(xié)議汗唱,etcd只支持http -
服務注冊
:支持兩種方式實現(xiàn)服務注冊宫莱,consul官方建議使用第二種方式。
- 一種是通過consul的服務注冊http API哩罪,由服務自己調(diào)用API實現(xiàn)注冊授霸,
- 另一種方式是通過json個是的配置文件實現(xiàn)注冊,將需要注冊的服務以json格式的配置文件給出际插。
-
服務發(fā)現(xiàn)
:支持兩種方式實現(xiàn)服務發(fā)現(xiàn)碘耳,
- 一種是通過http API來查詢有哪些服務,
- 另外一種是通過consul agent 自帶的DNS(8600端口)框弛,域名是以NAME.service.consul的形式給出辛辨,NAME即在定義的服務配置文件中,服務的名稱瑟枫。DNS方式可以通過check的方式檢查服務斗搞。
- 服務間的通信協(xié)議:Consul使用gossip協(xié)議管理成員關(guān)系、廣播消息到整個集群
結(jié)語
關(guān)于consul
的環(huán)境搭建以及應用后續(xù)再補充吧~
在github
上有關(guān)于Spring Cloud
完整的部署慷妙。
其它相關(guān)文章
Spring cloud(1)-簡介以及選擇
Spring cloud(2)-服務發(fā)現(xiàn)(Eureka僻焚,Consul)
Spring cloud(3)-負載均衡(Feign,Ribbon)
Spring cloud(4)-熔斷(Hystrix)
Spring cloud(5)-路由網(wǎng)關(guān)(Zuul)
Spring cloud(6)-配置管理及刷新(Config膝擂,Bus)
最后虑啤,給個 star 吧~
個人博客~
簡書~