Windows環境におけるConsulのインストールとマイクロサービスのサービス登録・発見

1. ダウンロードとインストール

公式サイトからダウンロードしてください:https://www.consul.io/downloads.html

ダウンロードしたファイルを解凍し、そのフォルダでコマンドプロンプトを開きます。以下のコマンドを実行して開発モードでConsulを起動します。

consul agent -dev

以下のようなメッセージが表示されれば起動成功です。UIは http://localhost:8500/ からアクセスできます。

環境変数を設定すれば、次回からコマンドプロンプトを開くだけでConsulを起動できます。

2. サービス登録と発見

2.1 サービス登録クラスの実装

まず、サービスをConsulに登録するためのクラスを作成します。このクラスは、アプリケーションの起動時にサービス情報を登録し、停止時に登録を解除します。

public class ServiceRegistrar
{
    private readonly IConfiguration _config;
    private readonly IHostApplicationLifetime _appLifetime;

    public ServiceRegistrar(IConfiguration configuration, IHostApplicationLifetime lifetime)
    {
        _config = configuration;
        _appLifetime = lifetime;
    }

    public void RegisterService()
    {
        var serviceIp = _config["ServiceIp"];
        var servicePort = int.Parse(_config["ServicePort"]);

        Console.WriteLine($"サービスヘルスチェックURL: http://{serviceIp}:{servicePort}/api/health/check");

        var consulClient = new ConsulClient(ConfigureConsulClient);
        var uniqueServiceId = $"ProductService-{Guid.NewGuid()}";

        var registration = new AgentServiceRegistration
        {
            ID = uniqueServiceId,
            Name = "ProductService",
            Address = serviceIp,
            Port = servicePort,
            Check = new AgentServiceCheck
            {
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                Interval = TimeSpan.FromSeconds(10),
                HTTP = $"http://{serviceIp}:{servicePort}/api/health/check",
                Timeout = TimeSpan.FromSeconds(5)
            }
        };

        consulClient.Agent.ServiceRegister(registration).Wait();

        // アプリケーションが停止する際に、サービス登録を解除する
        _appLifetime.ApplicationStopping.Register(() =>
        {
            Console.WriteLine($"サービス停止: {serviceIp}:{servicePort}");
            consulClient.Agent.ServiceDeregister(uniqueServiceId).Wait();
        });
    }

    private static void ConfigureConsulClient(ConsulClientConfiguration clientConfig)
    {
        clientConfig.Address = new Uri("http://127.0.0.1:8500");
        clientConfig.Datacenter = "dc1";
    }
}

2.2 アプリケーション起動時に登録処理を呼び出す

次に、ASP.NET Coreアプリケーションの起動時に、上記で作成したサービス登録クラスを呼び出します。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)
{
    // ... その他のミドルウェア設定

    // アプリケーション起動時にサービス登録を実行
    new ServiceRegistrar(Configuration, lifetime).RegisterService();
}

2.3 サービスの起動

複数のサービスインスタンスを起動して、Consulが正常にサービスを発見できるか確認します。以下のコマンドを異なるポートで実行します。

dotnet ProductService.dll --urls="http://*:5210" --ServiceIp="127.0.0.1" --ServicePort=5210
dotnet ProductService.dll --urls="http://*:5211" --ServiceIp="127.0.0.1" --ServicePort=5211
dotnet ProductService.dll --urls="http://*:5212" --ServiceIp="127.0.0.1" --ServicePort=5212

これらのコマンドを実行後、ConsulのUI(http://localhost:8500)を確認すると、登録されたサービスが表示されます。サービスに問題が発生した場合は、以下のエンドポイントでヘルスチェックの結果を確認できます:http://localhost:8500/v1/agent/checks。

3. クライアントによるサービスの利用

サービスディスカバリを行い、利用可能なサービスのいずれかにリクエストを送信するクライアントアプリケーションを作成します。

class ServiceDiscoveryClient
{
    private static List<string> _serviceEndpoints = new List<string>();

    static async Task Main(string[] args)
    {
        Console.WriteLine("利用可能なサービスのアドレスを一覧表示します。");
        await DiscoverServices();

        for (int i = 0; i < 15; i++)
        {
            Console.WriteLine("ランダムなサービスアドレスにリクエストを送信します。");
            var randomIndex = new Random().Next(_serviceEndpoints.Count);
            var targetUrl = _serviceEndpoints[randomIndex];

            Console.WriteLine($"リクエスト先のアドレス: {targetUrl}");
            using var httpClient = new HttpClient();
            var response = await httpClient.GetAsync(targetUrl);
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine($"{response.StatusCode}: {content}");
        }

        Console.ReadLine();
    }

    public static async Task DiscoverServices()
    {
        var consulClient = new ConsulClient();
        var services = await consulClient.Agent.Services();
        var registeredServices = services.Response.Values;

        foreach (var service in registeredServices)
        {
            var address = service.Address;
            var port = service.Port;
            var name = service.Service;

            Console.WriteLine($"アドレス: {address}:{port}, サービス名: {name}");
            _serviceEndpoints.Add($"http://{address}:{port}/api/products/getall");
        }
    }
}

このクライアントを実行すると、Consulから取得したサービスアドレスに対してランダムなリクエストが送信され、各サービスの応答がコンソールに表示されます。

タグ: .NET Consul マイクロサービス サービスディスカバリ

6月29日 17:00 投稿