使用Consul提供註冊和發現服務 什麼是 Consul Consul 是 HashiCorp 公司推出的開源工具,用於實現分散式系統的服務發現與配置。與其它分散式服務註冊與發現的方案,Consul 的方案更“一站式”,內置了服務註冊與發現框架、分佈一致性協議實現、健康檢查、Key/Value 存儲 ...
使用Consul提供註冊和發現服務
什麼是 Consul
Consul 是 HashiCorp 公司推出的開源工具,用於實現分散式系統的服務發現與配置。與其它分散式服務註冊與發現的方案,Consul 的方案更“一站式”,內置了服務註冊與發現框架、分佈一致性協議實現、健康檢查、Key/Value 存儲、多數據中心方案,不再需要依賴其它工具(比如 ZooKeeper 等)。使用起來也較為簡單。Consul 使用 Go 語言編寫,因此具有天然可移植性(支持Linux、windows和Mac OS X);安裝包僅包含一個可執行文件,方便部署,與 Docker 等輕量級容器可無縫配合。
Consul 安裝
訪問 Consul 官網 ,根據操作系統類型,選擇下載 Consul 的最新版本。我這裡選擇windows版本。
下載下來是一個zip壓縮包,解壓之後,是一個exe可執行文件。
打開CMD終端,進入consul.exe所在目錄,執行如下命令啟動Consul服務。
cd C:\consul_1.3.0_windows_amd64 # 進入consul.exe所在目錄
consul agent -dev # 啟動服務, -dev 表示開發模式運行,另外還有 -server 表示服務模式運行
啟動過程信息如下圖所示。
啟動成功之後,訪問 http://localhost:8500 , 可以查看 Consul 管理界面。
Consul 服務提供者
服務註冊發現中心有了,現在我們來開發服務提供者。
新建項目 spring-cloud-consul-producer,添加以下依賴。
pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
說明:
spring-boot-starter-actuator
健康檢查依賴於此包。
spring-cloud-starter-consul-discovery
Spring Cloud Consul 的支持。
註意添加Spring Cloud的依賴配置,完整內容參見源碼pom文件。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
添加配置
在配置文件添加內容如下。
application.yml
server: port: 8511 spring: application: name: spring-cloud-consul-producer cloud: consul: host: localhost port: 8500 discovery: serviceName: service-producer # 註冊到consul的服務名稱
Consul 的地址和埠號預設是 localhost:8500 ,如果不是這個地址可以自行配置,consul服務會占用8502介面,所以不要用8501、8502。spring.cloud.consul.discovery.serviceName
是指註冊到 Consul 的服務名稱,後期客戶端會根據這個名稱來進行服務調用。
修改啟動類
修改啟動器類,添加 @EnableDiscoveryClient 註解,開啟服務發現支持。
package com.louis.spring.cloud.consul.producer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class ConsuleProducerApplication { public static void main(String[] args) { SpringApplication.run(ConsuleProducerApplication.class, args); } }
添加服務
新建 HelloController,提供 hello 介面, 返回 hello consul 字元串。
package com.louis.spring.cloud.consul.producer.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "hello consul."; } }
為了模擬註冊均衡負載,複製一份上面的項目,重命名為 spring-cloud-consul-producer2 ,修改對應的埠為 8512,修改 hello 方法的返回值為:"helle consul two",修改完成後依次啟動兩個項目,啟動成功之後刷新Consul管理界面,發現我們註冊的service-producer服務,並有2個節點實例。
點擊進入節點詳情頁面,可以看到我們註冊的8511和8512兩個服務提供者節點實例。
Consul 消費者
服務註冊發現中心有了,服務提供者也有了,現在我們來開發服務消費者。
新建項目 spring-cloud-consul-comsumer,依賴同提供者。
添加配置
修改配置文件如下。
application.yml
server: port: 8521 spring: application: name: spring-cloud-consul-consumer cloud: consul: host: localhost port: 8500 discovery: register: false #設置不需要註冊到 consul 中
客戶端可以設置是否註冊到 Consul 中,具體需要根據我們的業務來選擇,一般在需要對外提供服務時進行註冊。
啟動器類
ConsuleConsumerApplication.java
package com.louis.spring.cloud.consul.producer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConsuleConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsuleConsumerApplication.class, args); } }
服務消費者
添加消費服務測試類,添加兩個介面,一個查詢所有我們註冊的服務,另一個從我們註冊的服務中選取一個服務,採用輪詢的方式。
ServiceController.java
package com.louis.spring.cloud.consul.producer.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ServiceController { @Autowired private LoadBalancerClient loadBalancerClient; @Autowired private DiscoveryClient discoveryClient; /** * 獲取所有服務 */ @RequestMapping("/services") public Object services() { return discoveryClient.getInstances("service-producer"); } /** * 從所有服務中選擇一個服務(輪詢) */ @RequestMapping("/discover") public Object discover() { return loadBalancerClient.choose("service-producer").getUri().toString(); } }
添加完成之後,啟動項目, 訪問 http://localhost:8521/services,返回兩個服務,分別是我們註冊的8511和8512。
[{ "serviceId": "service-producer", "host": "GG20J1G2E.logon.ds.ge.com", "port": 8511, "secure": false, "metadata": { "secure": "false" }, "uri": "http://GG20J1G2E.logon.ds.ge.com:8511", "scheme": null }, { "serviceId": "service-producer", "host": "GG20J1G2E.logon.ds.ge.com", "port": 8512, "secure": false, "metadata": { "secure": "false" }, "uri": "http://GG20J1G2E.logon.ds.ge.com:8512", "scheme": null }]
反覆訪問 http://localhost:8521/discover,結果交替返回服務8511和8512,因為預設的負載均衡器是採用輪詢的方式。
http://GG20J1G2E.logon.ds.ge.com:8511
http://GG20J1G2E.logon.ds.ge.com:8512
...
8511 和 8512 兩個服務會交替出現,從而實現了獲取服務端地址的均衡負載。
大多數情況下我們希望使用均衡負載的形式去獲取服務端提供的服務,因此使用第二種方法來模擬調用服務端提供的 hello 方法。
創建 CallHelloController.java
package com.louis.spring.cloud.consul.producer.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class CallHelloController { @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/call") public String call() { ServiceInstance serviceInstance = loadBalancer.choose("service-producer"); System.out.println("服務地址:" + serviceInstance.getUri()); System.out.println("服務名稱:" + serviceInstance.getServiceId()); String callServiceResult = new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/hello", String.class); System.out.println(callServiceResult); return callServiceResult; } }
使用 RestTemplate 進行遠程調用。添加完之後重啟 spring-cloud-consul-consumer 項目。
在瀏覽器中訪問地址:http://localhost:8521/call
,依次返回結果如下:
helle consul
helle consul two
...