註冊中心consul

ice_moss發表於2022-11-11

[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 協議》,轉載必須註明作者和本文連結

相關文章