Consul是一個分布式高可用服務網格解決方案,提供服務發現、配置、多資料中心等功能,最近試驗了一把服務網格、叢集等功能。
不說概念,直接上幹貨,怎麼搭建。
一.服務網格
官網案例:https://learn.hashicorp.com/consul/getting-started/connect
官網上有一個案例,有兩個服務 socat和web,他們都一個邊車代理,全部注冊到consul server上,使用web 的邊車 與socat的邊車通信,進而完成通路scoat服務。這個過程中,scoat和web 内部都沒有關于網絡通信的功能,全部由邊車完成。
但官網案例中,兩個服務和邊車、consul全部在一個機器裡,我認為展現不出服務網格的效果,是以把這個案例修改下,把web、socat、consul分别部署在不同的機器,通過邊車進行服務注冊、發現、調用。
我這裡用三台虛拟機, 機器一部署consul server(192.168.1.76),機器二部署socat和其邊車(192.168.1.77),機器三部署web邊車(192.168.1.75)
機器一部署consul:
consul有個特點,啟動時可以指定配置檔案,隻要配置檔案寫明A服務要注冊,啟動後在consul UI頁面上就會顯示,A服務已經注冊,即使A服務不存在,這點和eureka等注冊中心不同(必須由服務主動發起注冊)。
這一步和官網一樣,在consul目錄下建立 consul.d目錄,作配置目錄,裡面建兩個json檔案,作socat和web的注冊配置檔案。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2ITM3ETMzkDM1ADOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
socat.json内容: 裡面配置服務名是socat,所在address(官網案例沒有寫address,不寫預設在服務在consul本機上)、端口 ,以及邊車資訊,邊車代理了socat服務、邊車代理服務的IP、端口。
{
"service": {
"name": "socat",
"port": 8181,
"address":"192.168.1.77",
"connect": {
"sidecar_service": {
"proxy": {
"destination_service_name": "socat",
"destination_service_id": "socat",
"local_service_address": "192.168.1.77",
"local_service_port": 8181
}
}
}
}
}
web.json内容:與socat大緻相同,多了邊車的負載均衡配置,upstreams指定了 邊車将會監聽9191端口,發送到75機器上的9191端口,就會被邊車轉發到socat服務。
因為邊車啟動後,和consul相連,可以擷取到scoat的服務位址。
{
"service": {
"name": "web",
"address":"192.168.1.75",
"port":80,
"connect": {
"sidecar_service": {
"proxy": {
"destination_service_name": "web",
"destination_service_id": "web",
"local_service_address": "192.168.1.75",
"local_service_port": 80,
"upstreams": [
{
"destination_name": "socat",
"local_bind_port": 9191
}
]
}
}
}
}
}
随後将consul啟動:
consul agent -server -config-dir=./consul.d -dev -ui -client 0.0.0.0 -enable-script-checks
這些配置解釋在官網都有
- -server:以server模式啟動
- -config-dir:指定配置檔案路徑,服務注冊配置檔案
- -dev:以開發模式啟動,而不是叢集
- -ui:有ui頁面
- -client:指定可通路consul的IP,如果寫為固定IP,會發現其他IP都無法通路consul
- -enable-script-checks:允許通過配置檔案和http api注冊的服務
效果:consul特點,可以按配置檔案注冊服務,即使socat和web服務并沒有啟動。因為配置檔案沒有加健康檢查的配置,是以是健康執行個體,否則服務會是紅色标志。
機器二部署scoat和其邊車:
scoat是一個類似echo指令的程式,會将輸入字元串傳回。
啟動scoat服務:如果沒有安裝,會提示安裝,啟動成功後,相當于一個服務端,啟動在8181端口
socat -v tcp-l:8181,fork exec:"/bin/cat"
測試scoat: 與8181端口通信
nc 127.0.0.1 8181
啟動scoat邊車: -http-addr 參數指定了consul服務端位址,這個參數官網案例沒有,是以不指定會預設找本地的consul。
吐槽一句這個參數花了很久時間才找到。
consul connect proxy -http-addr=192.168.1.76:8500 -sidecar-for socat
機器三部署web的邊車
官網案例中,web服務并不存在,即雖然注冊中心有web服務資訊,但web服務并沒有真實啟動。
這不影響案例,隻要啟動了web邊車,就可以通過web邊車監聽的端口與socat通信,當然web邊車控制台會報錯,因為連不上web服務,沒關系不影響案例進行。
啟動web邊車:
consul connect proxy -http-addr=192.168.1.76:8500 -sidecar-for web
啟動後報錯,找不到本機80端口的web服務 ,因為在consul制定了web的端口為80。
在機器三與機器一的socat通信,通過web邊車所監聽的9191端口
nc 127.0.0.1 9191
成功:
總結
1.服務注冊、邊車代理的配置資訊都在consul server端,服務和邊車幾乎沒有配置資訊
2.服務調用還是要通過邊車所監聽的端口,如果web是個真實服務,那web編碼應該得在程式中寫死端口,或者寫在配置檔案,使用http通信或者其他通信方式,也是挺麻煩的,畢竟現在服務網格落地的方案少,還沒有太多案例可借鑒。
二.叢集
consul叢集最少使用三個節點,隻有三個節點才能完成leader選舉。
叢集搭建在這裡使用四台機器,三個虛拟機加本機,一會試一下leader當機後,重新選舉的過程。
機器一leader節點:
consul agent -server -bootstrap-expect=4 -data-dir=./data -node=server1 -bind=192.168.1.75 -client=0.0.0.0 -ui
- -bootstrap-expect=4 叢集期待四個節點
- -data-dir=./data 資料存放路徑
- -node=server1 節點名稱
- -bind=192.168.1.75 節點所在IP
建議啟動時把之前的data檔案夾删除,consul會按曆史資料去尋找曾經注冊服務記錄,如果服務不在了,還會一直報錯找不到。
機器二節點:
consul agent -server -bootstrap-expect=4 -data-dir=./data -node=server2 -bind=192.168.1.76 -client=0.0.0.0 -ui -join 192.168.1.75
- -join 192.168.1.75:指定節點的leader,要加入的叢集IP
機器三:
consul agent -server -bootstrap-expect=4 -data-dir=./data -node=server3 -bind=192.168.1.77 -client=0.0.0.0 -ui -join 192.168.1.75
機器四:
consul agent -ui -server -bootstrap-expect=4 -data-dir=X:\Geek\console\data -node=server4 -bind=192.168.1.74 -client=0.0.0.0 -join 192.168.1.75
全部啟動成功後,叢集才會列印日志說leader選舉成功。
三.整合springcloud
springcloudconsul提供了對consul功能的整合,簡單看一下
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
@EnableDiscoveryClient 可完成對consul、eureka、nacos全部注冊
@EnableDiscoveryClient
@SpringBootApplication
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
}
配置檔案指定consul所在位址,如果是叢集的話,隻需要寫叢集的一個節點就可以注冊上去,不需要全寫,這點跟eureka、nacos不同。
後面是健康檢查等等不說了。
server:
port: 9004
spring:
application:
name: consul-provider
cloud:
consul:
# host: 127.0.0.1 # consul 啟動位址
host: 192.168.1.75
port: 8500 # consul 啟動端口
discovery:
prefer-ip-address: true
health-check-interval: 5s
health-check-path: /actuator/health
hostname: 192.168.1.5
port: 9004
config:
enabled: true
啟動注冊成功後,完成feign調用都很簡單。
如果consul叢集中的leader節點當機的話,重新啟動服務注冊,會發現此時是無法注冊的,因為consul是沒有高可用特性,在leader重新選舉成功之前,整個叢集對外都不可用。