Spring cloud(2)-服務發現(Eureka,Consul)

在分佈式系統領域有個著名的CAP定理C-數據一致性A-服務可用性P-服務對網絡分區故障的容錯性,這三個特性在任何分佈式系統中不能同時知足,最多同時知足兩個); eureka是AP,zookeeper是CP。對於服務發現而言,可用性數據一致性更加劇要——AP賽過CPjava

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 節點的可用性來確保集羣數據的一致性。 git

    raft

  • paxos: 第一次由提交者Leader向全部其餘服務器發出prepare消息請求準備,全部服務器中大多數若是回覆諾言承諾就表示準備好了,能夠接受寫入;第二次提交者向全部服務器發出正式建議propose,全部服務器中大多數若是回覆已經接收就表示成功了。github

  • long polling:長輪詢,客戶端向服務器發送Ajax請求,服務器接到請求後hold住鏈接,直到有新消息才返回響應信息並關閉鏈接,客戶端處理完響應信息後再向服務器發送新的請求。web

  • metrics:做爲一款監控指標的度量類庫,它提供了不少模塊能夠爲第三方庫或者應用提供輔助統計信息, 它還能夠將度量數據發送給Ganglia和Graphite以提供圖形化的監控算法

  • Eureka的自我保護模式
    Eureka Server在運行期間,會統計心跳失敗的比例在15分鐘以內是否 低於85%,若是出現低於的狀況(實際在 生產環境上一般是因爲網 絡不穩定致使),Eureka Server會將當前的實例註冊信息保護起來,同時提 示警告。保護模式主要用於一組客戶端和Eureka Server之間存在網絡分 區場景下的保護。一旦進入保護模式,Eureka Server將會嘗試保護其服務注 冊表中的信息,再也不刪除服務註冊表中的數據(也就是不會註銷任何微服務)。
    因此Eureka的哲學是,同時保留」好數據「」壞數據「總比丟掉任何」好數據「要更好,因此這種模式在實踐中很是有效。,spring

爲啥不使用zookeeper作發現服務呢?

  1. ZooKeeper是分佈式協調服務,它的職責是保證數據(注:配置數據,狀態數據)在其管轄下的全部服務之間保持同步、一致;(強一致性)
  2. 發現服務的核心應該是須要強調服務的高可用
  3. ZooKeeper使用單一主進程Leader用於處理客戶端全部事務請求,採用ZAB協議將服務器數狀態以事務形式廣播到全部Follower上;若是三臺服務掛了兩臺怎麼選出leader1 不大於 (3/2)=1的
  4. 正確的設置與維護ZooKeeper服務就很是的困難
  5. 集羣中出現了網絡分割的故障(交換機故障致使交換機底下的子網間不能互訪)ZooKeeper會將它們都從本身管理範圍中剔除出去,外界就不能訪問到這些節點了,自己這些節點是「健康」的,能提供服務的
  6. 發現服務就算是返回了包含不實的信息的結果也比什麼都不返回要好(由於暫時的網絡故障而找不到可用的服務器)

所以, Eureka能夠很好的應對因網絡故障致使部分節點失去聯繫的狀況,而不會像zookeeper那樣使整個註冊服務癱瘓。json

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開啓負載均衡springboot

Ribbon是什麼?

RibbonNetflix發佈的開源項目,主要功能是提供客戶端的軟件負載均衡算法,將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的時候建立服務註冊中心,直接經過下載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官方建議使用第二種方式。
  1. 一種是經過consul的服務註冊http API,由服務本身調用API實現註冊,
  2. 另外一種方式是經過json個是的配置文件實現註冊,將須要註冊的服務以json格式的配置文件給出。
  • 服務發現:支持兩種方式實現服務發現,
  1. 一種是經過http API來查詢有哪些服務,
  2. 另一種是經過consul agent 自帶的DNS(8600端口),域名是以NAME.service.consul的形式給出,NAME即在定義的服務配置文件中,服務的名稱。DNS方式能夠經過check的方式檢查服務。
  • 服務間的通訊協議:Consul使用gossip協議管理成員關係、廣播消息到整個集羣

結語

關於consul的環境搭建以及應用後續再補充吧~
github上有關於Spring Cloud完整的部署。
其它相關文章
Spring cloud(1)-簡介以及選擇
Spring cloud(2)-服務發現(Eureka,Consul)
Spring cloud(3)-負載均衡(Feign,Ribbon)
Spring cloud(4)-熔斷(Hystrix)
Spring cloud(5)-路由網關(Zuul)
Spring cloud(6)-配置管理及刷新(Config,Bus)
最後,給個 star 吧~
我的博客~
簡書~

相關文章
相關標籤/搜索