使用Consul提供註冊和發現服務
以下內容親測成功,但還有些地方需要修改,特別是 spring.cloud.consul.discovery.instance-id,另外建議父子工程的方式,而不是三個工程專案。
坑:
什麼是 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
...
原始碼下載
碼雲:https://gitee.com/liuge1988/spring-cloud-demo.git
作者:朝雨憶輕塵
出處:https://www.cnblogs.com/xifengxiaoma/
版權所有,歡迎轉載,轉載請註明原文作者及出處。