原文: Consul基本使用
date: 2019-05-13 17:01:37html
前言
官網介紹Consul是一個分佈式服務網格(Service Mesh)解決方案... java
而我目前的理解是提供了分佈式系統中的服務發現和配置解決方案, 使用go實現, 目前在github的star是15k, 遠超Netflix Eurekagit
關於Consul的架構, 功能, 對比均可參考官網, 建議閱讀:github
目的spring
- 部署啓動consul開發環境 —— dev
- Spring Cloud Consul 基本使用
- consul中的服務發現
- consul中的配置中心
consul集羣部署 (下節)
下載&啓動
進入下載地址 下載對應的版本便可, 解壓即獲得可執行文件shell
這裏我下載最新版1.4.4
, 在Windows測試單機開發環境, 在Linux環境測試consul集羣部署bootstrap
進入命令行:bash
- 驗證版本:
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)
- 啓動:
consul agent -dev
正常啓動後, 打開 http://127.0.0.1:8500
能夠看到consul提供的UI, 長這個樣子架構
上述方式重啓不會保存數據, 能夠加入數據持久的參數app
$ consul agent -server -bootstrap -advertise 127.0.0.1 -data-dir ./data -ui
關於Consul的操做, 經常使用有兩種方式: CLI和UI, 後面會演示部分用法
Spring Cloud Consul
介紹: 略...
依賴
能夠選擇這個all
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
上面的all包含了如下三個依賴
<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>
也能夠根據實際須要選擇引入
- consul-discovery: 服務註冊和發現功能
- consul-bus: 消息總線,提供配置實時刷新,再也不依賴中間件
- consul-config: 配置中心
健康檢查
Spring Cloud Consul 默認會自動檢查端點 /actuator/health
能夠集成spring-boot-starter-actuator, 或者自定義這個端點:
@GetMapping("/actuator/health")
public String health() {
return "OK";
}
從consul ui中能夠看到檢查結果
HTTP GET http://thank-pc:8801/actuator/health: 200 Output: OK
服務間調用
準備如下兩個模塊: consul-provider(服務提供者), consul-consumer(服務消費者)
consul-provider
1, 引入上述pom依賴
2, bootstrap.yml
主要配置
spring:
application:
name: consul-provider
cloud:
consul:
host: 127.0.0.1
port: 8500
3, 提供接口
測試用, 隨便寫
@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 # 默認就是true, consumer能夠不註冊的也可設爲false
3, 調用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); }
測試
啓動consul後, consul-provider啓動兩個實例, consul-consumer啓動一個
查看Consul UI, 確保服務註冊成功
測試一下consul-comsumer中的兩個接口
GET http://localhost:8801/test/feignInvoke?name=thank
GET http://localhost:8801/test/restTemplateInvoke?name=thank
從訪問結果能夠看到consul-consumer找到了兩個服務提供者的實例, 並從中進行負載路由到其中一個
配置中心
從UI中可以看到, Consul也提供了配置中心的功能 —— Key/Value
規則
先進行一個簡單的put和get
使用CLI
# put
$ consul kv put name thank
Success! Data written to: name
# get
$ consul kv get name
thank
在Consul UI也能設置和查看
能夠輸入
consul kv --help
, 查看其餘幾個子命令的說明
爲了區分服務和profile, key支持目錄分類(key or folder), 用/
來區分, 例如:
$ consul kv put config/consul-provider/custom.address 北京
$ consul kv get /config/consul-provider/custom.address
北京
一樣, 在Consul UI也能夠這樣設置, 並以目錄的形式展示
Spring Cloud Consul配置實踐
在前面的pom依賴中可以看到其中的配置管理功能consul-config
與Spring Cloud Config不一樣的是, Consul中使用配置中心很簡易
在動態刷新配置時, 也沒有Spring Cloud Config中那樣須要依賴消息中間件和集成Spring Cloud Bus那麼麻煩
簡單測試
簡單測試配置屬性的讀取及動態刷新的功能
實際狀況下應該有一個配置中心的, 這裏測試爲了方便, 就用consul-provider中的配置作實驗
-
在配置文件
bootstrap.yml
中加入一個自定義配置custom: address: defaultAddress
-
在consul-provider中讀取該屬性
@Value("${custom.address}") public String address;
- 在Consul UI或命令行中添加一個配置
- key: config/consul-provider/custom.address
- value: 北京
接下來啓動consul-provider和consul-consumer, 訪問對應的API, 便可看到咱們添加的配置生效了
試着在Consul UI中修改config/consul-provider/custom.address
配置項的value值, 驗證動態刷新
注意點
- 第1步是爲了防止啓動無該屬性報錯, 若是第3步提早配置了該屬性, 那麼第1步能夠省略
- 爲了測試動態刷新的功能, 別忘了在屬性所在bean加上
@RefreshScope
註釋 - 注意優先級: 若是配置中心中的配置涉及到程序啓動, 那麼要放在
bootstrap.yml
中, 而非application.yml
, 這點與Spring Cloud Config同樣
可能注意到consul配置項中key: config/consul-provider/custom.address
兩個前綴是什麼意思
- custom.address: 對應yaml文件中的屬性
- consul-provider: 這個不用說了, 服務名
- config: Spring Cloud Consul中默認的前綴, 你能夠修改它
具體可參考
org.springframework.cloud.consul.config.ConsulConfigProperties#prefix
測試多profile
實驗多個profiles: default, dev, test
首先在consul中創建三個配置文件
-
default環境:
Key:consul-provider/data
Value:custom: env: default common: some common properties
-
dev環境
Key:consul-provider,dev/data
Value:custom: env: dev
-
test環境
Key:consul-provider,test/data
Value:custom: env: test
編寫測試接口
@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
的結果, 試着更改配置項的值, 驗證動態刷新
規則&配置總結
兩種鍵值類型
- key/value: 默認方式, 鍵值一一對應, 上述[簡單測試]演示的就是這種
- 值爲properties或yaml: [測試多profile]演示的是這種
經常使用配置
列舉幾個Spring Cloud Consul配置中心相關的經常使用配置項
在上面的示例中, 基本都使用了Spring Cloud Consul中的默認配置
相關配置項參考:
org.springframework.cloud.consul.config.ConsulConfigProperties
實際使用中可能須要修改, 經常使用的配置項列舉:
拿一個上面的配置對照: config/consul-provider,test/data
配置項(spring.cloud.consul.config.* ) |
含義 | 默認值 |
---|---|---|
default-context | 指定應用名 | application |
prefix | folder前綴 | config |
profile-separator | 環境分隔符 | , |
format | 枚舉類型, 還支持PROPERTIES, YAML, FILES | KEY_VALUE |
data-key | 當format是properties或yaml時, 將以該值做爲key去尋找對應配置 | data |
watch.* | 與配置刷新相關的 |
讀取規則
經過前面的演示, 基本也能猜出大概的規則, 例如test環境會讀取 config/consul-provider,test/data
對應的值
有一點須要注意, 在上面[測試多profile]中, 示例只在config/consul-provider/data
中配置了custom.common
, 指定test或dev環境後, 該配置也能讀出來
從這能夠看出consul-provider,xxx
與consul-provider
中的配置值通過了合併, 這與Spring Cloud Config同樣
把各環境都同樣的配置寫在這個默認會被讀取的配置中是個不錯的選擇
關於default-context
配置項, 默認爲application
, 在上面的實驗中, 在 consul-provider 項目中, 沒有配置 default-context,
也能找到配置中心對應的consul-provider,xxx
配置, 這與Spring Cloud Config中{name}-{profile}.yml
: 服務名-環境名的尋找規則同樣
即默認就會去找服務名對應的配置項, 若是配置中心的配置與服務名不一樣, 也支持你將default-context
設置成非服務名
若是配置中心中存在application配置, 例如config/application/data
, 那麼全部應用都會加載到它中的配置, 一樣適合作一些全部應用都公共的配置項
優先級
若是某個配置項, 例如custom.common
, 存在與如下四個配置中
config/{appname},dev/data
config/{appname}/data
config/application,dev/data
config/application/data
若是指定profile=dev
, 三者之間的優先級爲從上至下由高到低
配置刷新原理
在配置刷新原理上, Spring Cloud Config中實現動態刷新的原理是用消息隊列和bus實現以消息總線的方式進行通知配置信息的變化,
完成集羣上的自動化更新和批量配置屬性刷新.
Spring Cloud Consul 採用的是客戶端按期經過watch檢測consul中配置的變化, 而後觸發 Spring RefreshEvent 刷新上下文