首頁 > 軟體

Golang使用Consul詳解

2022-06-15 14:02:30

常用指令

agent指令

  • -bind=0.0.0.0 指定consul所在機器的ip地址
  • -http-port 指定web介面伺服器埠
  • -client 指定哪些機器可以存取consul, 0.0.0.0表示所有機器
  • -data-dir=path 指定服務資料檔案儲存位置
  • -dev 開發者模式,直接以預設模式啟動consul
  • -node=hostname 服務發現的名字
  • -rejoin consul啟動的時候,加入到的consul叢集
  • -server 以服務方式開啟server, 允許其他的consul連線到開啟的consul上,不加則以使用者端方式開啟
  • -ui 可以誰用web頁面來檢視服務發現的詳情
  • -config-dir 組態檔地址, 如果是資料夾會將所有檔案合併,裡面可以設定自己所在節點提供的服務
  • -bootstrap-expect 在一個叢集中期望提供的server節點數目,當該值提供時, consul一直等到達到指定的server數目才會參加選舉,推舉自己為leader。這個可以避免不一致和腦裂現象

啟動

consul agent -server -bootstrap-expect 1 -ui -rejoin -http-port=8080 -bind="127.0.0.1" -data-dir C:Windowstmp

members

檢視叢集中有多少成員

info

檢視當前系欸但資訊

leave

優雅關閉consul

reload

重新載入組態檔

常用功能

Consul最重要的的功能就是定義服務, 服務管理和健康檢查

定義服務

要定義一個服務, 有兩種方式:

  • 通過寫組態檔, 讓Consul讀取
  • 通過介面向Consul服務進行註冊

一般我們採用第二種方式, 但我們可以通過第一種方式的書寫規則來了解服務定義的一些選項

我們可以通過啟動時指定-config-dir來指定組態檔所在位置, 組態檔時json格式, 有多個會合並在一起

例子:

{
    "service": {
        "name": "redis", // 在consul面板上顯示的服務名
        "id": "redis", // 服務id, 一般通過服務id對服務進行管理, 若不指定則會使用name作為id
        "address": "127.0.0.1", // 服務地址
        "port": 80, // 服務執行的埠
        "tags": [
            "primary"
        ], // 服務的標籤, 可以作為服務的額外資訊
        //   服務健康檢查, 後面介紹
        "checks": [
            {
                "args": [
                    "/bin/check_redis",
                    "-p",
                    "7000"
                ],
                "interval": "30s",
                "timeout" : "60s"
            }
        ]
    }
}

服務管理

所謂服務管理就是指服務發現服務註冊服務登出

consul伺服器端均提供了相應的httpdns等方式的介面可以方便地操作,

一般我們用go是用官方提供的一個api庫進行操作, 對這些http的介面就不再過多贅述, 可以查閱官方檔案

Consul API

服務健康檢查

健康檢查是為了避免服務突然宕機而呼叫方不知道的情況發生, 原理就是隔一段時間通訊一次

consul提供了 tcpsslttludpscripthttp等多種方式來進行健康檢查,可以在服務註冊時指定健康檢查的方式

consul根據interval變數來決定多少時間間隔來通訊

根據timeout變數來決定傳送請求後多久未收到迴應算作失敗

這裡我們介紹三種, http|tcp|script方式

http方式

{
  "check": {
    "id": "api",
    "name": "HTTP API on port 5000",
    "http": "https://localhost:5000/health",   //呼叫介面
    "method": "POST",             
    "header": { "Content-Type": ["application/json"] },
    "body": "{"method":"health"}",
    "interval": "10s",   //
    "timeout": "1s"
  }
}

tcp方式

{
  "check": {
    "id": "ssh",
    "name": "SSH TCP on port 22",
    "tcp": "localhost:22",
    "interval": "10s",
    "timeout": "1s"
  }
}

script指令碼方式

指令碼方式略有不同,原理是通過呼叫指令碼,檢視指令碼的返回值來判斷健康檢查是否通過

指令碼退出程式碼為 0 : 通過健康檢查

1 : 警告 其他: 健康檢查失敗

{
  "check": {
    "id": "mem-util",
    "name": "Memory utilization",
    "args": ["/usr/local/bin/check_mem.py", "-limit", "256MB"],  // 會被拼成 /usr/local/bin/check_mem.py -limit 256MB 來進行呼叫
    "interval": "10s",
    "timeout": "1s"
  }
}

grpc方式

檢查grpc整個server狀態

{
  "check": {
    "id": "mem-util",
    "name": "Service health status",
    "grpc": "127.0.0.1:12345",
    "grpc_use_tls": true,      //是否使用tls, 預設不使用
    "interval": "10s"
  }
}

只檢查伺服器上的某一個服務

{
  "check": {
    "id": "mem-util",
    "name": "Service health status",
    "grpc": "127.0.0.1:12345/my_service",
    "grpc_use_tls": true,
    "interval": "10s"
  }
}

go使用官方api包來定義服務查詢服務

console的github官網提供了一個go包操作consul伺服器端的實現, 我們可以使用這個包來實現服務發現

那麼編寫一個使用consul註冊服務的伺服器端程式的核心邏輯是這樣:

  • 建立consul使用者端
  • 使用建立的consul使用者端連線相應的consul agent
  • 向consul註冊服務
  • 執行服務
  • 執行完畢後向consul登出服務

範例程式碼:

package main
import (
	"log"
	"net"

	"github.com/hashicorp/consul/api"
)
func main() {
	// 使用預設設定建立consul使用者端
	consulClient, err := api.NewClient(api.DefaultConfig())
	if err != nil {
		log.Fatal(err)
	}
	// 註冊服務
	// consulClient.Agent()先獲取當前機器上的consul agent節點
	consulClient.Agent().ServiceRegister(&api.AgentServiceRegistration{
		ID:      "MyService",
		Name:    "My Service",
		Address: "127.0.0.1",
		Port:    5050,
		Check: &api.AgentServiceCheck{
			CheckID:  "MyService",
			TCP:      "127.0.0.1:5050",
			Interval: "10s",
			Timeout:  "1s",
		},
	})
	// 執行完成後登出服務
	defer consulClient.Agent().ServiceDeregister("MyService")
	l, err := net.Listen("tcp", ":5050")
	if err != nil {
		log.Fatal(err)
	}
	for {
		conn, err := l.Accept()
		if err != nil {
			log.Fatal(err)
		}
		go func() {
			log.Printf("Ip: %s connected", conn.RemoteAddr().String())
		}()
	}
} 

我們通過tcp每10秒進行健康檢查, 輸出視窗每10秒就會輸出有新連線到來, 這是consul做的

$ go run .
2022/06/09 20:17:51 Ip: 127.0.0.1:53011 connected
2022/06/09 20:18:01 Ip: 127.0.0.1:53038 connected
2022/06/09 20:18:11 Ip: 127.0.0.1:53045 connected 

那麼服務的請求端(使用者端)需要通過consul來獲取服務的地址和埠,則需要這麼幾步:

  • 建立consul使用者端
  • 使用建立的consul使用者端連線相應的consul agent
  • 向consul請求相應服務id的註冊資訊
  • 如果獲取到了相應的註冊資訊, 就通過地址和埠請求服務

程式碼範例:

package main
import (
	"fmt"
	"log"
	"github.com/hashicorp/consul/api"
)
func main() {
	consulClient, err := api.NewClient(api.DefaultConfig())
	if err != nil {
		log.Fatal(err)
	}
	service, _, err := consulClient.Agent().Service("MyService", nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Got Service: ip-%s, port-%d", service.Address, service.Port)
}

保證伺服器端執行的情況執行使用者端:

$ go run .
Got Service: ip-127.0.0.1, port-5050

Consul使用Raft演演算法保證叢集一致性

到此這篇關於Golang使用Consul詳解的文章就介紹到這了,更多相關Golang Consul內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com