原文: Consul基本使用
date: 2019-05-13 17:01:37
[TOC]
前言
官網(wǎng)介紹Consul是一個(gè)分布式服務(wù)網(wǎng)格(Service Mesh)解決方案...
而我目前的理解是提供了分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和配置解決方案, 使用go實(shí)現(xiàn), 目前在github的star是15k, 遠(yuǎn)超Netflix Eureka
關(guān)于Consul的架構(gòu), 功能, 對(duì)比都可參考官網(wǎng), 建議閱讀:
目的
- 部署啟動(dòng)consul開發(fā)環(huán)境 —— dev
- Spring Cloud Consul 基本使用
- consul中的服務(wù)發(fā)現(xiàn)
- consul中的配置中心
consul集群部署 (下節(jié))
下載&啟動(dòng)
進(jìn)入下載地址 下載對(duì)應(yīng)的版本即可, 解壓即得到可執(zhí)行文件
這里我下載最新版1.4.4
, 在Windows測(cè)試單機(jī)開發(fā)環(huán)境, 在Linux環(huán)境測(cè)試consul集群部署
進(jìn)入命令行:
- 驗(yàn)證版本:
consul --version
λ consul --version
Consul v1.4.4
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
- 啟動(dòng):
consul agent -dev
正常啟動(dòng)后, 打開 http://127.0.0.1:8500
可以看到consul提供的UI, 長(zhǎng)這個(gè)樣子
上述方式重啟不會(huì)保存數(shù)據(jù), 可以加入數(shù)據(jù)持久的參數(shù)
$ consul agent -server -bootstrap -advertise 127.0.0.1 -data-dir ./data -ui
關(guān)于Consul的操作, 常用有兩種方式: CLI和UI, 后面會(huì)演示部分用法
Spring Cloud Consul
介紹: 略...
依賴
可以選擇這個(gè)all
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
上面的all包含了以下三個(gè)依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
</dependencies>
也可以根據(jù)實(shí)際需要選擇引入
- consul-discovery: 服務(wù)注冊(cè)和發(fā)現(xiàn)功能
- consul-bus: 消息總線塔逃,提供配置實(shí)時(shí)刷新,不再依賴中間件
- consul-config: 配置中心
健康檢查
Spring Cloud Consul 默認(rèn)會(huì)自動(dòng)檢查端點(diǎn) /actuator/health
可以集成spring-boot-starter-actuator, 或者自定義這個(gè)端點(diǎn):
@GetMapping("/actuator/health")
public String health() {
return "OK";
}
從consul ui中可以看到檢查結(jié)果
HTTP GET http://thank-pc:8801/actuator/health: 200 Output: OK
服務(wù)間調(diào)用
準(zhǔn)備以下兩個(gè)模塊: consul-provider(服務(wù)提供者), consul-consumer(服務(wù)消費(fèi)者)
consul-provider
1, 引入上述pom依賴
2, bootstrap.yml
主要配置
spring:
application:
name: consul-provider
cloud:
consul:
host: 127.0.0.1
port: 8500
3, 提供接口
測(cè)試用, 隨便寫
@GetMapping("getHello")
public String getHello(@RequestParam String name) throws Exception {
return String.format("[%s:%s] Hello %s", InetAddress.getLocalHost().getHostName(), this.port, name);
}
consul-comsumer
1, 引入上述pom依賴
2, bootstrap.yml
主要配置
spring:
application:
name: consul-comsumer
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
register: true # 默認(rèn)就是true, consumer可以不注冊(cè)的也可設(shè)為false
3, 調(diào)用consul-provider中的getHello()
這里用最常用的兩種方式 RestTemplate || Feign
-
RestTemplate
@GetMapping("restTemplateInvoke") public ResponseEntity<String> restTemplateInvoke(@RequestParam String name) { String url = "http://consul-provider/getHello?name=" + name; String result = this.restTemplate.getForObject(url, String.class); return new ResponseEntity(result, HttpStatus.OK); }
-
Feign
@FeignClient("consul-provider") public interface HelloClient { @GetMapping("getHello") String getHello(@RequestParam String name); } @GetMapping("feignInvoke") public ResponseEntity<String> feignInvoke(@RequestParam String name) { String result = this.helloClient.getHello(name); return new ResponseEntity(result, HttpStatus.OK); }
測(cè)試
啟動(dòng)consul后, consul-provider啟動(dòng)兩個(gè)實(shí)例, consul-consumer啟動(dòng)一個(gè)
查看Consul UI, 確保服務(wù)注冊(cè)成功
測(cè)試一下consul-comsumer中的兩個(gè)接口
GET http://localhost:8801/test/feignInvoke?name=thank
GET http://localhost:8801/test/restTemplateInvoke?name=thank
從訪問結(jié)果可以看到consul-consumer找到了兩個(gè)服務(wù)提供者的實(shí)例, 并從中進(jìn)行負(fù)載路由到其中一個(gè)
配置中心
從UI中能夠看到, Consul也提供了配置中心的功能 —— Key/Value
規(guī)則
先進(jìn)行一個(gè)簡(jiǎn)單的put和get
使用CLI
# put
$ consul kv put name thank
Success! Data written to: name
# get
$ consul kv get name
thank
在Consul UI也能設(shè)置和查看
可以輸入
consul kv --help
, 查看其他幾個(gè)子命令的說明
為了區(qū)分服務(wù)和profile, key支持目錄分類(key or folder), 用/
來區(qū)分, 例如:
$ consul kv put config/consul-provider/custom.address 北京
$ consul kv get /config/consul-provider/custom.address
北京
同樣, 在Consul UI也可以這樣設(shè)置, 并以目錄的形式展現(xiàn)
Spring Cloud Consul配置實(shí)踐
在前面的pom依賴中能夠看到其中的配置管理功能consul-config
與Spring Cloud Config不同的是, Consul中使用配置中心很簡(jiǎn)易
在動(dòng)態(tài)刷新配置時(shí), 也沒有Spring Cloud Config中那樣需要依賴消息中間件和集成Spring Cloud Bus那么麻煩
簡(jiǎn)單測(cè)試
簡(jiǎn)單測(cè)試配置屬性的讀取及動(dòng)態(tài)刷新的功能
實(shí)際情況下應(yīng)該有一個(gè)配置中心的, 這里測(cè)試為了方便, 就用consul-provider中的配置做實(shí)驗(yàn)
-
在配置文件
bootstrap.yml
中加入一個(gè)自定義配置custom: address: defaultAddress
-
在consul-provider中讀取該屬性
@Value("${custom.address}") public String address;
- 在Consul UI或命令行中添加一個(gè)配置
- key: config/consul-provider/custom.address
- value: 北京
接下來啟動(dòng)consul-provider和consul-consumer, 訪問對(duì)應(yīng)的API, 即可看到我們添加的配置生效了
試著在Consul UI中修改config/consul-provider/custom.address
配置項(xiàng)的value值, 驗(yàn)證動(dòng)態(tài)刷新
注意點(diǎn)
- 第1步是為了防止啟動(dòng)無該屬性報(bào)錯(cuò), 如果第3步提前配置了該屬性, 那么第1步可以省略
- 為了測(cè)試動(dòng)態(tài)刷新的功能, 別忘了在屬性所在bean加上
@RefreshScope
注釋 - 注意優(yōu)先級(jí): 如果配置中心中的配置涉及到程序啟動(dòng), 那么要放在
bootstrap.yml
中, 而非application.yml
, 這點(diǎn)與Spring Cloud Config一樣
可能注意到consul配置項(xiàng)中key: config/consul-provider/custom.address
兩個(gè)前綴是什么意思
- custom.address: 對(duì)應(yīng)yaml文件中的屬性
- consul-provider: 這個(gè)不用說了, 服務(wù)名
- config: Spring Cloud Consul中默認(rèn)的前綴, 你可以修改它
具體可參考
org.springframework.cloud.consul.config.ConsulConfigProperties#prefix
測(cè)試多profile
實(shí)驗(yàn)多個(gè)profiles: default, dev, test
首先在consul中建立三個(gè)配置文件
-
default環(huán)境:
Key:consul-provider/data
Value:custom: env: default common: some common properties
-
dev環(huán)境
Key:consul-provider,dev/data
Value:custom: env: dev
-
test環(huán)境
Key:consul-provider,test/data
Value:custom: env: test
編寫測(cè)試接口
@RestController
@RequestMapping("config")
@RefreshScope
public class ConfigController {
@Value("${custom.env}")
private String env;
@Value("${custom.common}")
private String common;
@GetMapping("getEnv")
public String getEnv() {
return "Environment: " + this.env + "\nCommon: " + this.common;
}
}
在 bootstrap.yml
中加入如下配置:
spring:
cloud:
consul:
config:
# default-context: consul-provider
format: YAML
profiles
active: dev
分別指定不同的 spring.profiles.active
, dev or test or none
觀察 curl localhost:8901/config/getEnv
的結(jié)果, 試著更改配置項(xiàng)的值, 驗(yàn)證動(dòng)態(tài)刷新
規(guī)則&配置總結(jié)
兩種鍵值類型
- key/value: 默認(rèn)方式, 鍵值一一對(duì)應(yīng), 上述[簡(jiǎn)單測(cè)試]演示的就是這種
- 值為properties或yaml: [測(cè)試多profile]演示的是這種
常用配置
列舉幾個(gè)Spring Cloud Consul配置中心相關(guān)的常用配置項(xiàng)
在上面的示例中, 基本都使用了Spring Cloud Consul中的默認(rèn)配置
相關(guān)配置項(xiàng)參考:
org.springframework.cloud.consul.config.ConsulConfigProperties
實(shí)際使用中可能需要修改, 常用的配置項(xiàng)列舉:
拿一個(gè)上面的配置對(duì)照: config/consul-provider,test/data
配置項(xiàng)(spring.cloud.consul.config.* ) |
含義 | 默認(rèn)值 |
---|---|---|
default-context | 指定應(yīng)用名 | application |
prefix | folder前綴 | config |
profile-separator | 環(huán)境分隔符 | , |
format | 枚舉類型, 還支持PROPERTIES, YAML, FILES | KEY_VALUE |
data-key | 當(dāng)format是properties或yaml時(shí), 將以該值作為key去尋找對(duì)應(yīng)配置 | data |
watch.* | 與配置刷新相關(guān)的 |
讀取規(guī)則
通過前面的演示, 基本也能猜出大概的規(guī)則, 例如test環(huán)境會(huì)讀取 config/consul-provider,test/data
對(duì)應(yīng)的值
有一點(diǎn)需要注意, 在上面[測(cè)試多profile]中, 示例只在config/consul-provider/data
中配置了custom.common
, 指定test或dev環(huán)境后, 該配置也能讀出來
從這可以看出consul-provider,xxx
與consul-provider
中的配置值經(jīng)過了合并, 這與Spring Cloud Config一樣
把各環(huán)境都一樣的配置寫在這個(gè)默認(rèn)會(huì)被讀取的配置中是個(gè)不錯(cuò)的選擇
關(guān)于default-context
配置項(xiàng), 默認(rèn)為application
, 在上面的實(shí)驗(yàn)中, 在 consul-provider 項(xiàng)目中, 沒有配置 default-context,
也能找到配置中心對(duì)應(yīng)的consul-provider,xxx
配置, 這與Spring Cloud Config中{name}-{profile}.yml
: 服務(wù)名-環(huán)境名的尋找規(guī)則一樣
即默認(rèn)就會(huì)去找服務(wù)名對(duì)應(yīng)的配置項(xiàng), 如果配置中心的配置與服務(wù)名不同, 也支持你將default-context
設(shè)置成非服務(wù)名
如果配置中心中存在application配置, 例如config/application/data
, 那么所有應(yīng)用都會(huì)加載到它中的配置, 同樣適合做一些所有應(yīng)用都公共的配置項(xiàng)
優(yōu)先級(jí)
如果某個(gè)配置項(xiàng), 例如custom.common
, 存在與以下四個(gè)配置中
config/{appname},dev/data
config/{appname}/data
config/application,dev/data
config/application/data
如果指定profile=dev
, 三者之間的優(yōu)先級(jí)為從上至下由高到低
配置刷新原理
在配置刷新原理上, Spring Cloud Config中實(shí)現(xiàn)動(dòng)態(tài)刷新的原理是用消息隊(duì)列和bus實(shí)現(xiàn)以消息總線的方式進(jìn)行通知配置信息的變化,
完成集群上的自動(dòng)化更新和批量配置屬性刷新.
Spring Cloud Consul 采用的是客戶端定期通過watch檢測(cè)consul中配置的變化, 然后觸發(fā) Spring RefreshEvent 刷新上下文