go學習筆記:使用 consul 做服務發現和配置共享

使用consul,其主要有四大特性:

1. 服務發現:利用服務註冊,服務發現功能來實現服務治理。

2. 健康檢查:利用consul註冊的檢查檢查函數或腳本來判斷服務是否健康,若服務不存在則從註冊中心移除該服務,減少故障服務請求。

3. k/v數據存儲:存儲kv數據,可以作爲服務配置中心來使用。

4. 多數據中心:可以建立多個consul集羣通過inter網絡進行互聯,進一步保證數據可用性。

通過docker安裝consul

docker pull consul:latest
//運行單機
docker run -d --restart=always --name consul -d -p 8500:8500 consul
 
/*
8500 http 端口,用於 http 接口和 web ui
8300 server rpc 端口,同一數據中心 consul server 之間通過該端口通信
8301 serf lan 端口,同一數據中心 consul client 通過該端口通信
8302 serf wan 端口,不同數據中心 consul server 通過該端口通信
8600 dns 端口,用於服務發現
-bbostrap-expect 2: 集羣至少兩臺服務器,才能選舉集羣leader
-ui:運行 web 控制檯
-bind: 監聽網口,0.0.0.0 表示所有網口,如果不指定默認未127.0.0.1,則無法和容器通信
-client : 限制某些網口可以訪問
*/
//集羣
docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:latest agent -server -bootstrap-expect 2 -ui -bind=0.0.0.0 -client=0.0.0.0
docker run --name consul2 -d -p 8501:8500 consul agent -server -ui -bind=0.0.0.0 -client=0.0.0.0 -join 172.17.0.2
docker run --name consul2 -d -p 8502:8500 consul agent -server -ui -bind=0.0.0.0 -client=0.0.0.0 -join 172.17.0.2

以下代碼實現一個服務註冊,服務發現,配置共享的功能:

package main
 
import (
    "net"
 
    "github.com/gin-gonic/gin"
 
    "fmt"
    "log"
    "net/http"
 
    consulapi "github.com/hashicorp/consul/api"
)
 
const (
    consulAddress = "192.168.100.19:8500"
    serviceId     = "111"
)
 
func main() {
    r := gin.Default()
 
    // consul健康檢查回調函數
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "ok",
        })
    })
    go http.ListenAndServe(":8081", r)
    // 註冊服務到consul
    ConsulRegister()
 
    // 從consul中發現服務
    ConsulFindServer()
 
    ConsulCheckHeath()
    ConsulKVTest()
    // 取消consul註冊的服務
    //ConsulDeRegister()
    var str string
    fmt.Scan(&str)
 
}
 
// 註冊服務到consul
func ConsulRegister() {
    // 創建連接consul服務配置
    config := consulapi.DefaultConfig()
    config.Address = consulAddress
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal("consul client error : ", err)
    }
 
    // 創建註冊到consul的服務到
    registration := new(consulapi.AgentServiceRegistration)
    registration.ID = serviceId                    // 服務節點的名稱
    registration.Name = "go-consul-test"           // 服務名稱
    registration.Port = 8081                       // 服務端口
    registration.Tags = []string{"go-consul-test"} // tag,可以爲空
    registration.Address = "192.168.3.42"          // 服務 IP 要確保consul可以訪問這個ip
 
    // 增加consul健康檢查回調函數
    check := new(consulapi.AgentServiceCheck)
    check.HTTP = fmt.Sprintf("http://%s:%d", registration.Address, registration.Port)
    check.Timeout = "5s"
    check.Interval = "5s"                        // 健康檢查間隔
    check.DeregisterCriticalServiceAfter = "30s" // 故障檢查失敗30s後 consul自動將註冊服務刪除
    registration.Check = check
 
    // 註冊服務到consul
    err = client.Agent().ServiceRegister(registration)
    if err == nil {
        fmt.Println("ConsulRegister done")
    }
}
 
// 取消consul註冊的服務
func ConsulDeRegister() {
    // 創建連接consul服務配置
    config := consulapi.DefaultConfig()
    config.Address = consulAddress
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal("consul client error : ", err)
    }
 
    client.Agent().ServiceDeregister(serviceId)
}
 
// 從consul中發現服務
func ConsulFindServer() {
    // 創建連接consul服務配置
    config := consulapi.DefaultConfig()
    config.Address = consulAddress
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal("consul client error : ", err)
    }
 
    // 獲取所有service
    services, _ := client.Agent().Services()
    for _, value := range services {
        fmt.Println("address:", value.Address)
        fmt.Println("port:", value.Port)
    }
 
    fmt.Println("=================================")
    // 獲取指定service
    service, _, err := client.Agent().Service(serviceId, nil)
    if err == nil {
        fmt.Println("address:", service.Address)
        fmt.Println("port:", service.Port)
    }
    if err == nil {
        fmt.Println("ConsulFindServer done")
    }
}
 
func ConsulCheckHeath() {
    // 創建連接consul服務配置
    config := consulapi.DefaultConfig()
    config.Address = consulAddress
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal("consul client error : ", err)
    }
 
    // 健康檢查
    a, b, _ := client.Agent().AgentHealthServiceByID(serviceId)
    fmt.Println("val1:", a)
    fmt.Println("val2:", b)
    fmt.Println("ConsulCheckHeath done")
}
 
func ConsulKVTest() {
    // 創建連接consul服務配置
    config := consulapi.DefaultConfig()
    config.Address = consulAddress
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal("consul client error : ", err)
    }
 
    // KV, put值
    values := "test"
    key := "go-consul-test"
    client.KV().Put(&consulapi.KVPair{Key: key, Flags: 0, Value: []byte(values)}, nil)
 
    // KV get值
    data, _, _ := client.KV().Get(key, nil)
    fmt.Println("data:", string(data.Value))
 
    // KV list
    datas, _, _ := client.KV().List("go", nil)
    for _, value := range datas {
        fmt.Println("val:", value)
    }
    keys, _, _ := client.KV().Keys("go", "", nil)
    fmt.Println("key:", keys)
    fmt.Println("ConsulKVTest done")
}
 
func localIP() string {
    addrs, err := net.InterfaceAddrs()
    if err != nil {
        return ""
    }
    for _, address := range addrs {
        if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
            if ipnet.IP.To4() != nil {
                return ipnet.IP.String()
            }
        }
    }
    return ""
}

運行結果:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章