← 記事一覧へ

Consul

Consul のサービス発見、ヘルスチェック、基本操作の記録。

Consul 原有学习记录

サービスが少なければ、設定に直接アドレスを書けます。インスタンスが増えると、アドレスの変更や一時的な障害に対応するため、「現在、このサービスにはどのインスタンスがあるか」を記録する場所が必要になります。Consul は登録、発見、ヘルスチェックを提供します。

1. 登録と発見とは

  • 登録:インスタンス ID、サービス名、アドレス、ポートを Consul に伝えます。
  • 発見:サービス名で条件に合うインスタンスを探し、呼び出す先を選びます。
  • ヘルスチェック:状態を記録し、異常なインスタンスを除外できるようにします。

登録済みと業務の利用可能性は別です。状態を確認し、呼び出しにはタイムアウトとエラー処理を設けます。チェック成功は次の要求の成功を保証しません。関連する API は 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 と サービス登録 API を併せて確認できます。

実際のアプリでは、業務サーバーを起動してから到達可能なアドレスを登録します。TTL は定期的に更新し、状態に応じて passing か critical を報告します。HTTP チェックを使う場合は、Consul agent からエンドポイントへ接続できることを確認します。

4. 注意点

サービス名とインスタンス ID は別です。複数のインスタンスが demo-api という名前でも、ID は別にしないと登録を上書きします。

アドレスは利用者が接続するものです。ここでの 127.0.0.1 は同じホスト上の呼び出しに限ります。機械やコンテナをまたぐ場合は、実際に到達できるアドレスを登録します。

登録解除だけでは障害に対応できないため、正常終了では解除し、強制終了にはヘルスチェックで対応します。正常な候補を検索しても、タイムアウトや接続失敗は処理します。

KV ストアを何でも保存するデータベースと考えないようにします。設定などには使えますが、権限、更新通知、読み取り失敗時の動作を検討します。

参考資料

Consul の文書、ヘルスチェック、1.21.3 のリリース記録。

この記事の日付について

旧日付の 2025-01-16 は公開履歴と一致しません。旧サイトで確認できる最初の公開日、2026-01-20 を採用しています。執筆日は未確認です。