Spring Cloud 支援很多服務發現的軟體,Eureka 只是其中之一,下面是 Spring Cloud 支援的服務發現軟體以及特性對比:
Consul 介紹
- Consul 是 HashiCorp 公司推出的開源工具,用於實現分散式系統的服務發現與配置。與其他分散式服務註冊與發現的方案,Consul 的方案更“一站式”,內建了服務註冊與發現框 架、分佈一致性協議實現、健康檢查、Key/Value 儲存、多資料中心方案,不再需要依賴其他工具(比如 ZooKeeper 等)。使用起來也較 為簡單。Consul 使用 Go 語言編寫,因此具有天然可移植性(支援Linux、windows和Mac OS X);安裝包僅包含一個可執行檔案,方便部署,與 Docker 等輕量級容器可無縫配合。
Consul 的優勢:
- 使用 Raft 演算法來保證一致性, 比複雜的 Paxos 演算法更直接. 相比較而言, zookeeper 採用的是 Paxos, 而 etcd 使用的則是 Raft。
- 支援多資料中心,內外網的服務採用不同的埠進行監聽。 多資料中心叢集可以避免單資料中心的單點故障,而其部署則需要考慮網路延遲, 分片等情況等。 zookeeper 和 etcd 均不提供多資料中心功能的支援。
- 支援健康檢查。 etcd 不提供此功能。
- 支援 http 和 dns 協議介面。 zookeeper 的整合較為複雜, etcd 只支援 http 協議。
- 官方提供 web 管理介面, etcd 無此功能。
- 綜合比較, Consul 作為服務註冊和配置管理的新星, 比較值得關注和研究。
特性
- 服務發現
- 健康檢查
- Key/Value 儲存
- 多資料中心
Consul 角色
- client: 客戶端, 無狀態, 將 HTTP 和 DNS 介面請求轉發給區域網內的服務端叢集。
- server: 服務端, 儲存配置資訊, 高可用叢集, 在區域網內與本地客戶端通訊, 通過廣域網與其他資料中心通訊。 每個資料中心的 server 數量推薦為 3 個或是 5 個。
Consul 安裝
Consul 不同於 Eureka 需要單獨安裝,訪問Consul 官網下載 Consul 的最新版本,
我這裡以 Windows 為例,下載下來是一個 consul_1.2.1_windows_amd64.zip 的壓縮包,解壓是是一個 consul.exe 的執行檔案。
cd 到對應的目錄下,使用 cmd 啟動 Consul
cd D:\Common Files\consul
#cmd啟動:
consul agent -dev # -dev表示開發模式執行,另外還有-server表示服務模式執行
複製程式碼
為了方便期間,可以在同級目錄下建立一個 run.bat 指令碼來啟動,指令碼內容如下
consul agent -dev
複製程式碼
啟動結果如下:
啟動成功之後訪問:http://localhost:8500,可以看到 Consul 的管理介面
這樣就意味著我們的 Consul 服務啟動成功了。
Linux環境安裝
把下載的linux下的安裝包consul拷貝到linux環境裡面,使用unzip進行解壓:
2,配置環境變數
vi /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_172
export MAVEN_HOME=/usr/local/apache-maven-3.5.4
export CONSUL_HOME=/usr/local/consul
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$CONSUL_HOME:$PATH
#上面的CONSUL_HOME就是consul的路徑,上面的配置僅供參考。
source /etc/profile #命令使配置生效
#檢視安裝的consul版本
[root@CentOS124 /]# consul -v
Consul v1.2.2
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
[root@CentOS124 /]#
複製程式碼
Consul 服務端
建立一個 spring-cloud-consul-producer 專案 依賴包如下:
<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.application.name=spring-cloud-consul-producer
server.port=8501
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
#註冊到consul的服務名稱
spring.cloud.consul.discovery.serviceName=service-producer
複製程式碼
- Consul 的地址和埠號預設是 localhost:8500 ,如果不是這個地址可以自行配置。
- spring.cloud.consul.discovery.serviceName 是指註冊到 Consul 的服務名稱,後期客戶端會根據這個名稱來進行服務呼叫。
啟動類
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulProducerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulProducerApplication.class, args);
}
}
複製程式碼
新增了 @EnableDiscoveryClient 註解表示支援服務發現。
建立一個 Controller,推文提供 hello 的服務
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "helle consul";
}
}
複製程式碼
為了模擬註冊均衡負載複製一份上面的專案重新命名為 spring-cloud-consul-producer-2 ,修改對應的埠為 8502,修改 hello 方法的返回值為:"helle consul two",修改完成後依次啟動兩個專案。
這時候我們再次在瀏覽器訪問地址:http://localhost:8500 就會顯示出來兩個服務提供者
Consul 消費端
建立一個 spring-cloud-consul-consumer 專案,pom 檔案和上面示例保持一致
配置檔案內容如下
spring.application.name=spring-cloud-consul-consumer
server.port=8503
spring.cloud.consul.host=127.0.0.1
spring.cloud.consul.port=8500
#設定不需要註冊到 consul 中
spring.cloud.consul.discovery.register=false
複製程式碼
客戶端可以設定註冊到 Consul 中,也可以不註冊到 Consul 註冊中心中,根據我們的業務來選擇,只需要在使用服務時通過 Consul 對外提供的介面獲取服務資訊即可。
啟動類
@SpringBootApplication
public class ConsulConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulConsumerApplication.class, args);
}
}
複製程式碼
進行測試
建立一個 ServiceController ,試試如果去獲取 Consul 中的服務
@RestController
public class ServiceController {
@Autowired
private LoadBalancerClient loadBalancer;
@Autowired
private DiscoveryClient discoveryClient;
//獲取所有服務
@RequestMapping("/services")
public Object services() {
return discoveryClient.getInstances("service-producer");
}
//從所有服務中選擇一個服務(輪詢)
@RequestMapping("/discover")
public Object discover() {
return loadBalancer.choose("service-producer").getUri().toString();
}
}
複製程式碼
Controller 中有倆個方法,一個是獲取所有服務名為service-producer的服務資訊並返回到頁面,一個是隨機從服務名為service-producer的服務中獲取一個並返回到頁面。
新增完 ServiceController 之後我們啟動專案,訪問地址:http://localhost:8503/services,返回jsn資料
[{"serviceId":"service-producer","host":"windows10.microdone.cn","port":8501,"secure":false,"metadata":{"secure":"false"},"uri":"http://windows10.microdone.cn:8501","scheme":null},{"serviceId":"service-producer","host":"windows10.microdone.cn","port":8502,"secure":false,"metadata":{"secure":"false"},"uri":"http://windows10.microdone.cn:8502","scheme":null}]
複製程式碼
發現我們剛才建立的埠為 8501 和 8502 的兩個服務端都存在
多次訪問地址:http://localhost:8503/discover,頁面會交替返回資訊:
說明 8501 和 8501 的兩個服務會交替出現,從而實現了獲取服務端地址的均衡負載。
大多數情況下我們希望使用均衡負載的形式去獲取服務端提供的服務,因此使用第二種方法來模擬呼叫服務端提供的 hello 方法。
建立 CallHelloController :
@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:8503/call,依次返回結果如下:
helle consul
helle consul two
複製程式碼
說明我們已經成功的呼叫了 Consul 服務端提供的服務,並且實現了服務端的均衡負載功能
示例程式碼:github.com/ityouknow/s…