2018-06-16-Spring cloud(2)-服務(wù)發(fā)現(xiàn)(Eureka,Consul)

在分布式系統(tǒng)領(lǐng)域有個(gè)著名的CAP定理C-數(shù)據(jù)一致性;A-服務(wù)可用性P-服務(wù)對(duì)網(wǎng)絡(luò)分區(qū)故障的容錯(cuò)性,這三個(gè)特性在任何分布式系統(tǒng)中不能同時(shí)滿足,最多同時(shí)滿足兩個(gè));
eureka是AP,zookeeper是CP。對(duì)于服務(wù)發(fā)現(xiàn)而言,可用性數(shù)據(jù)一致性更加重要——AP勝過(guò)CP

Consul zookeeper euerka etcd
服務(wù)健康檢查 服務(wù)狀態(tài),內(nèi)存,硬盤(pán)等 (弱)長(zhǎng)連接,keepalive 可配支持 連接心跳
多數(shù)據(jù)中心 支持
kv存儲(chǔ)服務(wù) 支持 支持 支持
一致性 raft paxos raft
CAP ca cp ap cp
使用接口(多語(yǔ)言能力) 支持http和dns 客戶端 http(sidecar) http/grpc
watch支持(客戶端觀察到服務(wù)提供者變化) 全量/支持long polling 支持 支持long polling/大部分增量 支持long polling
自身監(jiān)控 metrics metrics metrics
安全 acl /https acl https支持(弱)
spring cloud集成 已支持 已支持 已支持 已支持
  • raft:Raft強(qiáng)依賴(lài) Leader 節(jié)點(diǎn)的可用性來(lái)確保集群數(shù)據(jù)的一致性。

    raft

  • paxos: 第一次由提交者Leader向所有其他服務(wù)器發(fā)出prepare消息請(qǐng)求準(zhǔn)備,所有服務(wù)器中大多數(shù)如果回復(fù)諾言承諾就表示準(zhǔn)備好了,可以接受寫(xiě)入;第二次提交者向所有服務(wù)器發(fā)出正式建議propose,所有服務(wù)器中大多數(shù)如果回復(fù)已經(jīng)接收就表示成功了。

  • long polling:長(zhǎng)輪詢(xún),客戶端向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器接到請(qǐng)求后hold住連接,直到有新消息才返回響應(yīng)信息并關(guān)閉連接,客戶端處理完響應(yīng)信息后再向服務(wù)器發(fā)送新的請(qǐng)求。

  • metrics:作為一款監(jiān)控指標(biāo)的度量類(lèi)庫(kù),它提供了很多模塊可以為第三方庫(kù)或者應(yīng)用提供輔助統(tǒng)計(jì)信息, 它還可以將度量數(shù)據(jù)發(fā)送給Ganglia和Graphite以提供圖形化的監(jiān)控

  • Eureka的自我保護(hù)模式
    Eureka Server在運(yùn)行期間,會(huì)統(tǒng)計(jì)心跳失敗的比例在15分鐘之內(nèi)是否
    低于85%,如果出現(xiàn)低于的情況(實(shí)際在
    生產(chǎn)環(huán)境上通常是由于網(wǎng)
    絡(luò)不穩(wěn)定導(dǎo)致),Eureka Server會(huì)將當(dāng)前的實(shí)例注冊(cè)信息保護(hù)起來(lái),同時(shí)提
    示警告。保護(hù)模式主要用于一組客戶端和Eureka Server之間存在網(wǎng)絡(luò)分
    區(qū)場(chǎng)景下的保護(hù)。一旦進(jìn)入保護(hù)模式,Eureka Server將會(huì)嘗試保護(hù)其服務(wù)注
    冊(cè)表中的信息,不再刪除服務(wù)注冊(cè)表中的數(shù)據(jù)(也就是不會(huì)注銷(xiāo)任何微服務(wù))。
    所以Eureka的哲學(xué)是,同時(shí)保留”好數(shù)據(jù)“”壞數(shù)據(jù)“總比丟掉任何”好數(shù)據(jù)“要更好,所以這種模式在實(shí)踐中非常有效。,

為啥不使用zookeeper做發(fā)現(xiàn)服務(wù)呢?

  1. ZooKeeper是分布式協(xié)調(diào)服務(wù),它的職責(zé)是保證數(shù)據(jù)(注:配置數(shù)據(jù),狀態(tài)數(shù)據(jù))在其管轄下的所有服務(wù)之間保持同步、一致;(強(qiáng)一致性)
  2. 發(fā)現(xiàn)服務(wù)的核心應(yīng)該是需要強(qiáng)調(diào)服務(wù)的高可用
  3. ZooKeeper使用單一主進(jìn)程Leader用于處理客戶端所有事務(wù)請(qǐng)求,采用ZAB協(xié)議將服務(wù)器數(shù)狀態(tài)以事務(wù)形式廣播到所有Follower上;如果三臺(tái)服務(wù)掛了兩臺(tái)怎么選出leader;1 不大于 (3/2)=1的
  4. 正確的設(shè)置與維護(hù)ZooKeeper服務(wù)就非常的困難
  5. 集群中出現(xiàn)了網(wǎng)絡(luò)分割的故障(交換機(jī)故障導(dǎo)致交換機(jī)底下的子網(wǎng)間不能互訪)ZooKeeper會(huì)將它們都從自己管理范圍中剔除出去,外界就不能訪問(wèn)到這些節(jié)點(diǎn)了,本身這些節(jié)點(diǎn)是“健康”的,能提供服務(wù)的
  6. 發(fā)現(xiàn)服務(wù)就算是返回了包含不實(shí)的信息的結(jié)果也比什么都不返回要好(因?yàn)闀簳r(shí)的網(wǎng)絡(luò)故障而找不到可用的服務(wù)器)

因此, Eureka可以很好的應(yīng)對(duì)因網(wǎng)絡(luò)故障導(dǎo)致部分節(jié)點(diǎn)失去聯(lián)系的情況,而不會(huì)像zookeeper那樣使整個(gè)注冊(cè)服務(wù)癱瘓。

Spring Cloud Eureka(服務(wù)注冊(cè))

  • 添加依賴(lài)
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
  • 開(kāi)啟服務(wù)注冊(cè)

通過(guò) @EnableEurekaServer注解啟動(dòng)一個(gè)服務(wù)注冊(cè)中心提供給其他應(yīng)用進(jìn)行對(duì)話,這個(gè)注解需要在springboot工程的啟動(dòng)application類(lèi)上加

    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(服務(wù)提供者)

  • 服務(wù)提供方
  • 將自身服務(wù)注冊(cè)到 Eureka 注冊(cè)中心,從而使服務(wù)消費(fèi)方能夠找到
  • 添加依賴(lài)
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
  • 開(kāi)啟服務(wù)注冊(cè)
    在應(yīng)用主類(lèi)中通過(guò)加上 @EnableEurekaClient,但只有Eureka 可用,你也可以使用@EnableDiscoveryClient。需要配置才能找到Eureka注冊(cè)中心服務(wù)器
    discovery service有許多種實(shí)現(xiàn)(eureka、consul、zookeeper等)
    @EnableDiscoveryClient基于spring-cloud-commons,
    @EnableEurekaClient基于spring-cloud-netflix。
    就是如果選用的注冊(cè)中心是eureka,那么就推薦@EnableEurekaClient
    如果是其他的注冊(cè)中心,那么推薦使用@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服務(wù)器
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: eureka-provider
server:
  port: 8081

Spring Cloud Service Consumer(服務(wù)消費(fèi)者)

Eureka注冊(cè)服務(wù),消費(fèi)者使用Ribbon開(kāi)啟負(fù)載均衡

Ribbon是什么?

RibbonNetflix發(fā)布的開(kāi)源項(xiàng)目,主要功能是提供客戶端的軟件負(fù)載均衡算法,將Netflix的中間層服務(wù)連接在一起。Ribbon客戶端組件提供一系列完善的配置項(xiàng)如連接超時(shí),重試等。簡(jiǎn)單的說(shuō),就是在配置文件中列出Load Balancer(簡(jiǎn)稱(chēng)LB)后面所有的機(jī)器,Ribbon會(huì)自動(dòng)的幫助你基于某種規(guī)則(如簡(jiǎn)單輪詢(xún),隨即連接等)去連接這些機(jī)器。我們也很容易使用Ribbon實(shí)現(xiàn)自定義的負(fù)載均衡算法。

Ribbon的核心組件

Ribbon在工作時(shí)首選會(huì)通過(guò)ServerList來(lái)獲取所有可用的服務(wù)列表,然后通過(guò)ServerListFilter過(guò)慮掉一部分地址,最后在剩下的地址中通過(guò)IRule選擇出一臺(tái)服務(wù)器作為最終結(jié)果。

  • ServerList:用于獲取地址列表。它既可以是靜態(tài)的(提供一組固定的地址),也可以是動(dòng)態(tài)的(從注冊(cè)中心中定期查詢(xún)地址列表)。
  • ServerListFilter:僅當(dāng)使用動(dòng)態(tài)ServerList時(shí)使用,用于在原始的服務(wù)列表中使用一定策略過(guò)慮掉一部分地址。
  • IRule:選擇一個(gè)最終的服務(wù)地址作為LB結(jié)果。選擇策略有輪詢(xún)、根據(jù)響應(yīng)時(shí)間加權(quán)、斷路器(當(dāng)Hystrix可用時(shí))等。

Ribbon提供的主要負(fù)載均衡策略

  • 簡(jiǎn)單輪詢(xún)負(fù)載均衡(RoundRobin) 以輪詢(xún)的方式依次將請(qǐng)求調(diào)度不同的服務(wù)器,即每次調(diào)度執(zhí)行i = (i + 1) mod n,并選出第i臺(tái)服務(wù)器。
  • 隨機(jī)負(fù)載均衡 (Random) 隨機(jī)選擇狀態(tài)為UP的Server
  • 加權(quán)響應(yīng)時(shí)間負(fù)載均衡 (WeightedResponseTime) 根據(jù)相應(yīng)時(shí)間分配一個(gè)weight,相應(yīng)時(shí)間越長(zhǎng),weight越小,被選中的可能性越低。
  • 區(qū)域感知輪詢(xún)負(fù)載均衡(ZoneAvoidanceRule) :復(fù)合判斷server所在區(qū)域的性能和server的可用性選擇server

服務(wù)提供者(提供服務(wù))

  • 開(kāi)啟服務(wù)注冊(cè)
    注冊(cè)三臺(tái)
@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

服務(wù)消費(fèi)者(依賴(lài)于其它服務(wù))

  • pom.xml添加依賴(lài)
<!-- 客戶端負(fù)載均衡 -->
<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>
  • 開(kāi)啟服務(wù)負(fù)載均衡
    通過(guò)@EnableDiscoveryClient向服務(wù)注冊(cè)中心注冊(cè);并且向程序的ioc注入一個(gè)bean: restTemplate并通過(guò)@LoadBalanced注解表明這個(gè)restRemplate開(kāi)啟負(fù)載均衡的功能
@EnableDiscoveryClient
@SpringBootApplication
public class RibbonConsumerApplication {
    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(RibbonConsumerApplication.class, args);
    }
}
  • 消費(fèi)提供者方法
/**
 * 描述:調(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
    指定服務(wù)的注冊(cè)中心地址,配置自己的服務(wù)端口,服務(wù)名稱(chēng)
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

spring:
  application:
    name: ribbon-consumer

server:
  port: 9000

依次啟動(dòng)服務(wù)(Eureka服務(wù),三臺(tái)service provider和service Consumer),查看ribbon是否開(kāi)啟負(fù)載均衡

Spring Cloud Consul(針對(duì)Consul的服務(wù)治理實(shí)現(xiàn))

由于Consul自身提供了服務(wù)端,所以我們不需要像之前實(shí)現(xiàn)Eureka的時(shí)候創(chuàng)建服務(wù)注冊(cè)中心,直接通過(guò)下載consul的服務(wù)端程序就可以使用。
Consul內(nèi)置了服務(wù)注冊(cè)發(fā)現(xiàn)框架(一站式)、具有以下性質(zhì)(參考上面列表):

  • 分布一致性協(xié)議實(shí)現(xiàn)
  • 健康檢查
  • Key/Value存儲(chǔ)
  • 多數(shù)據(jù)中心方案

Consul的優(yōu)勢(shì)

  • 使用 Raft 算法來(lái)保證一致性, 比復(fù)雜的 Paxos 算法更直接
  • 支持多數(shù)據(jù)中心,內(nèi)外網(wǎng)的服務(wù)采用不同的端口進(jìn)行監(jiān)聽(tīng)
  • 多數(shù)據(jù)中心集群可以避免單數(shù)據(jù)中心的單點(diǎn)故障,而其部署則需要考慮網(wǎng)絡(luò)延遲, 分片等情況等
  • 支持健康檢查
  • 支持 http 和 dns 協(xié)議接口
  • 官方提供web管理界面

Consul的角色

  • client:客戶端, 無(wú)狀態(tài), 將 HTTP 和 DNS 接口請(qǐng)求轉(zhuǎn)發(fā)給局域網(wǎng)內(nèi)的服務(wù)端集群,所有注冊(cè)到當(dāng)前節(jié)點(diǎn)的服務(wù)會(huì)被轉(zhuǎn)發(fā)到server,本身是不持久化這些信息
  • server:服務(wù)端, 保存配置信息, 高可用集群, 在局域網(wǎng)內(nèi)與本地客戶端通訊,功能和client都一樣,唯一不同的是,它會(huì)把所有的信息持久化的本地,這樣遇到故障,信息是可以被保留的。 通過(guò)廣域網(wǎng)與其他數(shù)據(jù)中心通訊. 每個(gè)數(shù)據(jù)中心的 server 數(shù)量推薦為 3 個(gè)或是 5 個(gè).
  • server-leader:表明這個(gè)server是它們的老大,它和其它server不一樣的一點(diǎn)是,它需要負(fù)責(zé)同步注冊(cè)的信息給其它的server,同時(shí)也要負(fù)責(zé)各個(gè)節(jié)點(diǎn)的健康監(jiān)測(cè)。
  • raft:server節(jié)點(diǎn)之間的數(shù)據(jù)一致性保證,一致性協(xié)議使用的是raft,而zookeeper用的paxos,etcd采用的也是taft。
  • 服務(wù)發(fā)現(xiàn)協(xié)議:consul采用http和dns協(xié)議,etcd只支持http
  • 服務(wù)注冊(cè):支持兩種方式實(shí)現(xiàn)服務(wù)注冊(cè),consul官方建議使用第二種方式。
  1. 一種是通過(guò)consul的服務(wù)注冊(cè)http API,由服務(wù)自己調(diào)用API實(shí)現(xiàn)注冊(cè),
  2. 另一種方式是通過(guò)json個(gè)是的配置文件實(shí)現(xiàn)注冊(cè),將需要注冊(cè)的服務(wù)以json格式的配置文件給出。
  • 服務(wù)發(fā)現(xiàn):支持兩種方式實(shí)現(xiàn)服務(wù)發(fā)現(xiàn),
  1. 一種是通過(guò)http API來(lái)查詢(xún)有哪些服務(wù),
  2. 另外一種是通過(guò)consul agent 自帶的DNS(8600端口),域名是以NAME.service.consul的形式給出,NAME即在定義的服務(wù)配置文件中,服務(wù)的名稱(chēng)。DNS方式可以通過(guò)check的方式檢查服務(wù)。
  • 服務(wù)間的通信協(xié)議:Consul使用gossip協(xié)議管理成員關(guān)系、廣播消息到整個(gè)集群

結(jié)語(yǔ)

關(guān)于consul的環(huán)境搭建以及應(yīng)用后續(xù)再補(bǔ)充吧~
github上有關(guān)于Spring Cloud完整的部署。
其它相關(guān)文章
Spring cloud(1)-簡(jiǎn)介以及選擇
Spring cloud(2)-服務(wù)發(fā)現(xiàn)(Eureka,Consul)
Spring cloud(3)-負(fù)載均衡(Feign,Ribbon)
Spring cloud(4)-熔斷(Hystrix)
Spring cloud(5)-路由網(wǎng)關(guān)(Zuul)
Spring cloud(6)-配置管理及刷新(Config,Bus)
最后,給個(gè) star 吧~
個(gè)人博客~
簡(jiǎn)書(shū)~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容