[toc]
文章介紹
本文我們將介紹什麼是consul,為什麼需要consul, consul的安裝, 服務註冊, 健康檢查, 服務發現
什麼是consul
官方介紹:
Consul is a service networking solution to automate network configurations, discover services, and enable secure connectivity across any cloud or runtime
翻譯:Consul是一種服務網路解決方案,可自動化網路配置、發現服務並支援跨任何雲或執行時的安全連線。
這裡列舉一個consul使用場景:微服務中,會將整個服務拆分為多個微服務,當多個微服務之間進行呼叫時,就需要進行配置,這個過程更好對解決方案是使用consul對各個微服務做服務發現,例如A服務,B服務,C服務,D服務,E服務在服務啟動時,我們將其註冊到consul中,當ABCDE之間進行相互呼叫時,各個微服務就可以從consul中做服務發現,拿到需要呼叫的服務的資訊,然後再去呼叫服務就可以了
consul的安裝
這裡我們使用docker安裝
docker run -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600/udp consul consul agent -dev -client=0.0.0.0
開機啟動consul
docker container update --restart=always 容器名字
瀏覽器訪問 127.0.0.1:8500
服務註冊
這裡我們直接使用go做服務註冊
這裡需要拉取github.com/hashicorp/consul/api
go get github.com/hashicorp/consul/api
註冊http服務:
package main
import (
"fmt"
"net"
"github.com/hashicorp/consul/api"
)
//Register 註冊服務至註冊中心
func Register(address string, port int, name string, tags []string, id string) error {
//DefaultConfig 返回客戶端的預設配置
cfg := api.DefaultConfig()
//安裝consul的ip:port
cfg.Address = "10.2.69.164:8500"
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
//生成對應的檢查物件
check := &api.AgentServiceCheck{
HTTP: "http://10.2.69.164:5001/health",
Timeout: "5s",
Interval: "5s",
DeregisterCriticalServiceAfter: "10s",
}
//生成註冊物件
registration := new(api.AgentServiceRegistration)
registration.Name = name
registration.ID = id
registration.Port = port
registration.Tags = tags
registration.Address = address
registration.Check = check
err = client.Agent().ServiceRegister(registration)
if err != nil {
panic(err)
}
return nil
}
func main(){
tags := []string{"ice_moss", "inventory", "server", "golang"}
Register("10.2.69.164", 5001, "inventory", tags, "inventory-srv")
}
仔細看的話就會發現問題,我們整個過程並沒有啟動:"http://10.2.69.164:5001/health
如果我們註冊的是grpc服務的話就需要這樣配置:
//生成對應的檢查物件
check := &api.AgentServiceCheck{
GRPC: fmt.Sprintf("%s:%d", global.ServerConfig.Host, *Port),
Timeout: "5s",
Interval: "5s",
DeregisterCriticalServiceAfter: "15s",
}
我們到consul中雖然可以看到inventory-srv
的資訊,但是這個服務是掛掉的
所以我們還需要做健康檢查
健康檢查
這裡我們之間修改上述程式碼:
package main
import (
"fmt"
"net"
"github.com/gin-gonic/gin"
"github.com/hashicorp/consul/api"
)
//Register 註冊服務至註冊中心
func Register(address string, port int, name string, tags []string, id string) error {
//DefaultConfig 返回客戶端的預設配置
cfg := api.DefaultConfig()
//安裝consul的ip:port
cfg.Address = "10.2.69.164:8500"
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
//生成對應的檢查物件
check := &api.AgentServiceCheck{
HTTP: "http://10.2.69.164:5001/health",
Timeout: "5s",
Interval: "5s",
DeregisterCriticalServiceAfter: "10s",
}
//生成註冊物件
registration := new(api.AgentServiceRegistration)
registration.Name = name
registration.ID = id
registration.Port = port
registration.Tags = tags
registration.Address = address
registration.Check = check
err = client.Agent().ServiceRegister(registration)
if err != nil {
panic(err)
}
return nil
}
func main(){
tags := []string{"ice_moss", "inventory", "server", "golang"}
Register("10.2.69.164", 5001, "inventory", tags, "inventory-srv")
router := gin.Default()
router.GET("health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "test",
})
})
err := router.Run(":5001")
if err != nil {
panic(err)
}
這樣我們就可以成功註冊服務到consul中了,這樣consul會在http://10.2.69.164:5001/health一直輪詢檢查我們的服務
服務發現
當我們的註冊服務時可以對consul做服務發現,看看這個有哪些服務註冊到consul中,下面直接看程式碼:
package main
import (
"fmt"
"net"
"net/http"
"github.com/gin-gonic/gin"
"github.com/hashicorp/consul/api"
)
//Register 註冊服務至註冊中心
func Register(address string, port int, name string, tags []string, id string) error {
//DefaultConfig 返回客戶端的預設配置
cfg := api.DefaultConfig()
cfg.Address = "10.2.69.164:8500"
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
//生成對應的檢查物件
check := &api.AgentServiceCheck{
HTTP: "http://10.2.69.164:5001/health",
Timeout: "5s",
Interval: "5s",
DeregisterCriticalServiceAfter: "10s",
}
//生成註冊物件
registration := new(api.AgentServiceRegistration)
registration.Name = name
registration.ID = id
registration.Port = port
registration.Tags = tags
registration.Address = address
registration.Check = check
err = client.Agent().ServiceRegister(registration)
if err != nil {
panic(err)
}
return nil
}
//AllServices 發現所有服務
func AllServices() {
//配置
cfg := api.DefaultConfig()
cfg.Address = "10.2.69.164:8500"
//將配置寫入物件中
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
data, err := client.Agent().Services()
if err != nil {
panic(err)
}
for key, v := range data {
fmt.Println("key:", key, "address:", v.Address, "port:", v.Port)
}
}
func main() {
//開啟協程
go AllServices()
tags := []string{"ice_moss", "inventory", "server", "golang"}
Register("10.2.69.164", 5001, "inventory", tags, "inventory-srv")
Register("10.2.69.164", 5001, "user-web", []string{"user-web", "ice_moss"}, "user-web")
router := gin.Default()
router.GET("health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "test",
})
})
err := router.Run(":5001")
if err != nil {
panic(err)
}
}
其中輸出:
key: inventory-srv address: 10.2.69.164 port: 5001
key: user-web address: 10.2.69.164 port: 5001
當我們需要發現指定服務:
//FilterService 服務發現
func FilterService() {
cfg := api.DefaultConfig()
cfg.Address = "10.2.69.164:8500"
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
//服務name
data, err := client.Agent().ServicesWithFilter(`Service == "user-web"`)
if err != nil {
panic(err)
}
for key, _ := range data {
fmt.Println(key)
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結