轉載請標明出處:
http://blog.csdn.net/forezp/a...
本文出自 方誌朋的博客
Consul是HashiCorp公司推出的開源軟件,使用GO語言編寫,提供了分佈式系統的服務註冊和發現、配置等功能,這些功能中的每個均可以根據須要單獨使用,也能夠一塊兒使用以構建全方位的服務網格。Consul不只具備服務治理的功能,並且使用分佈式一致協議RAFT算法實現,有多數據中心的高可用方案,而且很容易和Spring Cloud等微服務框架集成,使用起來很是的簡單,具備簡單、易用、可插排等特色。使用簡而言之,Consul提供了一種完整的服務網格解決方案 。html
每一個提供服務的節點都運行了Consul的代理,運行代理不須要服務發現和獲取配置的KV鍵值對,代理只負責監控檢查。代理節點能夠和一個或者多個Consul server通信。 Consul服務器是存儲和複製數據的地方。服務器自己選出了領導者。雖然Consul能夠在一臺服務器上運行,但建議使用3到5,以免致使數據丟失的故障狀況。建議爲每一個數據中心使用一組Consul服務器。
若是你的組件須要發現服務,能夠查詢任何Consul Server或任何Consul客戶端,Consul客戶端會自動將查詢轉發給Consul Server。
須要發現其餘服務或節點的基礎架構組件能夠查詢任何Consul服務器或任何Consul代理。代理會自動將查詢轉發給服務器。每一個數據中心都運行Consul服務器集羣。發生跨數據中心服務發現或配置請求時,本地Consul服務器會將請求轉發到遠程數據中心並返回結果。java
術語mysql
讓咱們分解這張圖並描述每一個部分。首先,咱們能看到有兩個數據中心,標記爲「1」和「2」。Consul對多數據中心有一流的支持而且但願這是一個常見的狀況。ios
在每一個數據中心,client和server是混合的。通常建議有3-5臺server。這是基於有故障狀況下的可用性和性能之間的權衡結果,由於越多的機器加入達成共識越慢。然而,並不限制client的數量,它們能夠很容易的擴展到數千或者數萬臺。程序員
同一個數據中心的全部節點都必須加入gossip協議。這意味着gossip協議包含一個給定數據中心的全部節點。這服務於幾個目的:第一,不須要在client上配置server地址。發現都是自動完成的。第二,檢測節點故障的工做不是放在server上,而是分佈式的。這是的故障檢測相比心跳機制有更高的可擴展性。第三:它用來做爲一個消息層來通知事件,好比leader選舉發生時。web
每一個數據中心的server都是Raft節點集合的一部分。這意味着它們一塊兒工做並選出一個leader,一個有額外工做的server。leader負責處理全部的查詢和事務。做爲一致性協議的一部分,事務也必須被複制到全部其餘的節點。由於這一要求,當一個非leader得server收到一個RPC請求時,它將請求轉發給集羣leader。面試
server節點也做爲WAN gossip Pool的一部分。這個Pool不一樣於LAN Pool,由於它是爲了優化互聯網更高的延遲,而且它只包含其餘Consul server節點。這個Pool的目的是爲了容許數據中心可以以low-touch的方式發現彼此。這使得一個新的數據中心能夠很容易的加入現存的WAN gossip。由於server都運行在這個pool中,它也支持跨數據中心請求。當一個server收到來自另外一個數據中心的請求時,它隨即轉發給正確數據中想一個server。該server再轉發給本地leader。算法
這使得數據中心之間只有一個很低的耦合,可是因爲故障檢測,鏈接緩存和複用,跨數據中心的請求都是相對快速和可靠的。spring
Consul在業界最普遍的用途就是做爲服務註冊中心,同Eureka類型,consul做爲服務註冊中心,它的註冊和發現過程以下圖:sql
在上面的流程圖上有三個角色,分別爲服務註冊中心、服務提供者、服務消費者。
Eureka是一種服務發現工具。 該體系結構主要是客戶端/服務器,每一個數據中心有一組Eureka服務器,一般每一個可用區域一個。 一般,Eureka的客戶使用嵌入式SDK來註冊和發現服務。 對於非本地集成的客戶端,使用Ribbon等邊車經過Eureka透明地發現服務。
Eureka使用盡力而爲的複製提供弱一致的服務視圖。 當客戶端向服務器註冊時,該服務器將嘗試複製到其餘服務器但不提供保證。 服務註冊的生存時間很短(TTL),要求客戶端對服務器進行心跳檢測。 不健康的服務或節點將中止心跳,致使它們超時並從註冊表中刪除。 發現請求能夠路由到任何服務,因爲盡力複製,這些服務能夠提供過期或丟失的數據。 這種簡化的模型容許輕鬆的集羣管理和高可擴展性。
Consul提供了一系列超級功能,包括更豐富的運行情況檢查,鍵/值存儲和多數據中心感知。 Consul須要每一個數據中心中的一組服務器,以及每一個客戶端上的代理,相似於使用像Ribbon這樣的邊車。 Consul代理容許大多數應用程序不知道Consul,經過配置文件執行服務註冊以及經過DNS或負載平衡器sidecars進行發現。
Consul提供強大的一致性保證,由於服務器使用Raft協議複製狀態。 Consul支持豐富的運行情況檢查,包括TCP,HTTP,Nagios / Sensu兼容腳本或基於的Eureka的TTL。 客戶端節點參與基於gossip的健康檢查,該檢查分發健康檢查的工做,而不像集中式心跳,這成爲可擴展性挑戰。 發現請求被路由到當選的Consul領導者,這使他們默認狀況下很是一致。 容許過期讀取的客戶端容許任何服務器處理其請求,從而容許像Eureka同樣的線性可伸縮性。
Consul的強烈一致性意味着它能夠用做領導者選舉和集羣協調的鎖定服務。 Eureka不提供相似的保證,而且一般須要爲須要執行協調或具備更強一致性需求的服務運行ZooKeeper。
Consul提供了支持面向服務的體系結構所需的功能工具包。 這包括服務發現,還包括豐富的運行情況檢查,鎖定,鍵/值,多數據中心聯合,事件系統和ACL。 Consul和consul-template和envconsul等工具生態系統都試圖最大限度地減小集成所需的應用程序更改,以免須要經過SDK進行本機集成。 Eureka是更大的Netflix OSS套件的一部分,該套件指望應用程序相對同質且緊密集成。 所以,Eureka只解決了有限的一部分問題,指望其餘工具如ZooKeeper能夠同時使用。
Eureka Server端採用的是P2P的複製模式,可是它不保證複製操做必定能成功,所以它提供的是一個最終一致性的服務實例視圖;Client端在Server端的註冊信息有一個帶期限的租約,一旦Server端在指按期間沒有收到Client端發送的心跳,則Server端會認定爲Client端註冊的服務是不健康的,定時任務將會將其從註冊表中刪除。Consul與Eureka不一樣,Consul採用Raft算法,能夠提供強一致性的保證,Consul的agent至關於Netflix Ribbon + Netflix Eureka Client,並且對應用來講相對透明,同時相對於Eureka這種集中式的心跳檢測機制,Consul的agent能夠參與到基於goosip協議的健康檢查,分散了server端的心跳檢測壓力。除此以外,Consul爲多數據中心提供了開箱即用的原生支持等。
Consul採用Go語言編寫,支持Linux、Mac、Windows等各大操做系統,本文使用windows操做系統,下載地址:https://www.consul.io/downloa...,下完成後解壓到計算機目錄下,解壓成功後,只有一個可執行的consul.exe可執行文件。打開cmd終端,切換到目錄,執行如下命令:
consul --version
終端顯示以下:
Consul v1.4.2 Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use p rotocol >2 when speaking to compatible agents)
證實consul下載成功了,並可執行。
consul的一些常見的執行命令以下:
命令 | 解釋 | 示例 |
---|---|---|
agent | 運行一個consul agent | consul agent -dev |
join | 將agent加入到consul集羣 | consul join IP |
members | 列出consul cluster集羣中的members | consul members |
leave | 將節點移除所在集羣 | consul leave |
更多命令請查看官方網站:https://www.consul.io/docs/co...
開發模式啓動:
consul agent -dev
啓動成功,在瀏覽器上訪問:http://localhost:8500,顯示的界面以下:
該項目經過自動配置並綁定到Spring環境和其餘Spring編程模型成語,爲Spring Boot應用程序提供Consul集成。經過幾個簡單的註釋,您能夠快速啓用和配置應用程序中的常見模式,並使用基於Consul的組件構建大型分佈式系統。提供的模式包括服務發現,控制總線和配置。智能路由(Zuul)和客戶端負載平衡(Ribbon),斷路器(Hystrix)經過與Spring Cloud Netflix的集成提供。
本小節以案例的形式來說解如何使用Spring Cloud Consul來進行服務註冊和發現的,而且使用Feign來消費服務。再講解以前,已經啓動consul的agent,而且在瀏覽器上http://localhost:8500可以顯示正確的頁面。本案例一共有2個工程,分別以下:
工程名 | 端口 | 描述 |
---|---|---|
consul-provider | 8763 | 服務提供者 |
consul-consumer | 8765 | 服務消費者 |
其中,服務提供者和服務消費者分別向consul註冊,註冊完成後,服務消費者經過FeignClient來消費服務提供者的服務。
建立一個工程consul-provider,在工程的pom文件引入如下依賴,包括consul-discovery的起步依賴,該依賴是spring cloud consul用來向consul 註冊和發現服務的依賴,採用REST API的方式進行通信。另外加上web的起步依賴,用於對外提供REST API。代碼以下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
在工程的配置文件application.yml作下如下配置:
server: port: 8763 spring: application: name: consul-provider cloud: consul: host: localhost port: 8500 discovery: serviceName: consul-provider
上面的配置,指定了程序的啓動端口爲8763,應用名爲consul-provider,consul註冊中心的地址爲localhost:8500
在程序員的啓動類ConsulProviderApplication加上@EnableDiscoveryClient註解,開啓服務發現的功能。
@SpringBootApplication @EnableDiscoveryClient public class ConsulProviderApplication { public static void main(String[] args) { SpringApplication.run(ConsulProviderApplication.class, args); } }
寫一個RESTAPI,該API爲一個GET請求,返回當前程序的啓動端口,代碼以下。
@RestController public class HiController { @Value("${server.port}") String port; @GetMapping("/hi") public String home(@RequestParam String name) { return "hi "+name+",i am from port:" +port; } }
啓動工程,在瀏覽器上訪問http://localhost:8500,頁面顯示以下:
從上圖可知,consul-provider服務已經成功註冊到consul上面去了。
服務消費者的搭建過程同服務提供者,在pom文件中引入的依賴同服務提供者,在配置文件application.yml配置同服務提供者,不一樣的點在端口爲8765,服務名爲consul-consumer。
寫一個FeignClient,該FeignClient調用consul-provider的REST API,代碼以下:
@FeignClient(value = "consul-provider") public interface EurekaClientFeign { @GetMapping(value = "/hi") String sayHiFromClientEureka(@RequestParam(value = "name") String name); }
Service層代碼以下:
@Service public class HiService { @Autowired EurekaClientFeign eurekaClientFeign; public String sayHi(String name){ return eurekaClientFeign.sayHiFromClientEureka(name); } }
對外提供一個REST API,該API調用了consul-provider的服務,代碼以下:
@RestController public class HiController { @Autowired HiService hiService; @GetMapping("/hi") public String sayHi(@RequestParam( defaultValue = "forezp",required = false)String name){ return hiService.sayHi(name); } }
在瀏覽器上訪問http://localhost:8765/hi,瀏覽器響應以下:
hi forezp,i am from port:8763
這說明consul-consumer已經成功調用了consul-provider的服務。這說明consul-provider的服務已經註冊到了consul的註冊中心上面去了。consul-consumer可以獲取註冊中心的註冊列表來獲來消費服務。
Consul不只能用來服務註冊和發現,Consul並且支持Key/Value鍵值對的存儲,能夠用來作配置中心。Spring Cloud 提供了Spring Cloud Consul Config依賴去和Consul相集成,用來作配置中心。
如今以案例的形式來說解如何使用Consul做爲配置中心,本案例在上一個案例的consul-provider基礎上進行改造。首先在工程的pom文件加上consul-config的起步依賴,代碼以下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-config</artifactId> </dependency>
而後在配置文件application.yml加上如下的如下的配置,配置以下:
spring: profiles: active: dev
上面的配置指定了SpringBoot啓動時的讀取的profiles爲dev。
而後再工程的啓動配置文件bootstrap.yml文件中配置如下的配置:
spring: application: name: consul-provider cloud: consul: host: localhost port: 8500 discovery: serviceName: consul-provider config: enabled: true format: yaml prefix: config profile-separator: ':' data-key: data
關於spring.cloud.consul.config的配置項描述以下:
網頁上訪問consul的KV存儲的管理界面,即http://localhost:8500/ui/dc1/kv,建立一條記錄,
key值爲:config/consul-provider:dev/data
value值以下:
foo: bar: bar1 server: port: 8081
在consul-provider工程新建一個API,該API返回從consul 配置中心讀取foo.bar的值,代碼以下:
@RestController public class FooBarController { @Value("${foo.bar}") String fooBar; @GetMapping("/foo") public String getFooBar() { return fooBar; } }
啓動工程,能夠看到程序的啓動端口爲8081,便是consul的配置中心配置的server.port端口。
工程啓動完成後,在瀏覽器上訪問http://localhost:8081/foo,頁面顯示bar1。由此可知,應用consul-provider已經成功從consul的配置中心讀取了配置foo.bar的配置。
當使用spring cloud config做爲配置中心的時候,可使用spring cloud config bus支持動態刷新配置。Spring Cloud Comsul Config默認就支持動態刷新,只須要在須要動態刷新的類上加上@RefreshScope註解便可,修改代碼以下:
@RestController @RefreshScope public class FooBarController { @Value("${foo.bar}") String fooBar; @GetMapping("/foo") public String getFooBar() { return fooBar; } }
啓動consul-provider工程,在瀏覽器上訪問http://localhost:8081/foo,頁面顯示bar1。而後
在網頁上訪問consul的KV存儲的管理界面,即http://localhost:8500/ui/dc1/kv,修改config/consul-provider:dev/data的值,修改後的值以下:
foo: bar: bar2 server: port: 8081
此時不從新啓動consul-provider,在瀏覽器上訪問http://localhost:8081/foo,頁面顯示bar2。可見foo.bar的最新配置在應用不重啓的狀況下已經生效。
https://www.consul.io/intro/i...
https://www.consul.io/docs/in...
https://www.consul.io/intro/v...
http://www.ityouknow.com/spri...
https://springcloud.cc/spring...
https://www.cnblogs.com/lsf90...
https://blog.csdn.net/longgeq...