
服務少的時候,可以在配置裡直接寫地址。例項多起來,地址會變,某個例項還可能暫時不可用,這時就需要一個地方記錄“這個服務現在有哪些例項”。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 是開發模式,退出後不能依靠它儲存生產狀態。容器裡監聽所有地址,是為了讓埠對映能訪問;宿主機對映仍然限制在本地。


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