← 返回文章列表

Consul

記錄 Consul 的服務發現、健康檢查與基礎使用。

Consul 原有學習記錄

服務少的時候,可以在配置裡直接寫地址。例項多起來,地址會變,某個例項還可能暫時不可用,這時就需要一個地方記錄“這個服務現在有哪些例項”。Consul 可以提供服務註冊、發現和健康檢查等能力。

1、註冊和發現是什麼?

  • 註冊:把例項 ID、服務名、地址和埠告訴 Consul。
  • 發現:按服務名查詢符合條件的例項,再選擇一個進行呼叫。
  • 健康檢查:記錄例項狀態,讓呼叫方能夠過濾異常例項。

“已註冊”和“業務可用”要分開。消費者要查詢健康狀態,而且呼叫仍然需要超時和錯誤處理;健康檢查不能保證下一次請求必然成功。相關介面見 Health API。

2、安裝和啟動

這裡用 Docker 啟動一個本地開發例項。示例固定在 1.21.3,方便對照舊學習環境,不代表推薦生產環境停留在該版本。

docker run -d \
  --name dev-consul \
  -p 127.0.0.1:8500:8500 \
  hashicorp/consul:1.21.3 agent -dev -client=0.0.0.0

瀏覽器訪問 http://127.0.0.1:8500。-dev 是開發模式,退出後不能依靠它儲存生產狀態。容器裡監聽所有地址,是為了讓埠對映能訪問;宿主機對映仍然限制在本地。

Consul 啟動記錄

Consul 介面記錄

3、在 Go 中完成一次註冊與發現

先在新的示例目錄初始化模組:

go mod init example.com/consul-demo

下面儲存為 main.go,再執行後面的依賴安裝指令。

package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/hashicorp/consul/api"
)

func run() error {
	cfg := api.DefaultConfig()
	cfg.Address = "127.0.0.1:8500"
	cfg.HttpClient = &http.Client{Timeout: 3 * time.Second}
	client, err := api.NewClient(cfg)
	if err != nil {
		return err
	}
	registration := &api.AgentServiceRegistration{
		ID: "demo-api-1", Name: "demo-api",
		Address: "127.0.0.1", Port: 18080,
		Check: &api.AgentServiceCheck{TTL: "15s"},
	}
	if err := client.Agent().ServiceRegister(registration); err != nil {
		return err
	}
	defer func() {
		if err := client.Agent().ServiceDeregister(registration.ID); err != nil {
			fmt.Println("注销失败:", err)
		}
	}()
	if err := client.Agent().UpdateTTL("service:demo-api-1", "demo heartbeat", "passing"); err != nil {
		return err
	}
	services, _, err := client.Health().Service("demo-api", "", true, nil)
	if err != nil {
		return err
	}
	for _, entry := range services {
		fmt.Printf("%s %s:%d\n", entry.Service.ID, entry.Service.Address, entry.Service.Port)
	}
	return nil
}

func main() {
	if err := run(); err != nil {
		fmt.Fprintln(os.Stderr, "Consul 示例失败:", err)
		os.Exit(1)
	}
}

儲存程式碼後,安裝示例使用的 SDK 版本並執行:

go get github.com/hashicorp/consul/api@v1.30.0
go mod tidy
go run .

這個版本用於復現上面的 API 示例;後續更換版本時重新驗證,並保留 go.mod 和 go.sum。程式演示“註冊 → 更新 TTL 心跳 → 查詢健康例項 → 退出時登出”。它沒有啟動 18080 上的真實業務服務,地址只是示例後設資料;列印出地址不等於業務介面已經可用了。Go SDK 介面與服務註冊 API可以對照著看。

真正接到應用裡,先啟動業務服務,再註冊可達地址。TTL 心跳要週期性更新,並且結合自己的狀態決定報 passing 還是 critical;如果希望 Consul 主動檢查介面,可以換成 HTTP 檢查,確認 Consul agent 能訪問對應地址。

4、容易踩的坑

服務名和例項 ID 不一樣。多個例項可以都叫 demo-api,但 ID 應該各不相同,否則會覆蓋註冊資訊。

地址是給消費者用的。這裡的 127.0.0.1 只適合同一臺宿主機上的呼叫方。跨機器或跨容器呼叫時,要註冊呼叫方實際能訪問的地址。

登出不是故障處理的全部。正常退出可以登出,程序被強制結束時還要依靠健康檢查。發現時查詢健康例項,呼叫時繼續處理超時與連線失敗。

KV 儲存也不是隨便換個資料庫。可以用於配置等場景,但要考慮許可權、更新通知和讀取失敗時的行為。

參考資料

Consul 文件、健康檢查、1.21.3 版本記錄。

關於這篇文章的日期

舊日期 2025-01-16 與文章發布記錄不符,現按舊站可確認的首次發布日 2026-01-20 整理。實際創作日期尚無法確認。

原始日期: 2025-01-16 21:15:06 +0800