.Net 使用 Consul

Consul windows部署见上篇 Consul Windows部署 - 咸鱼翻身? - 博客园 (cnblogs.com)

一、创建Web API 项目并安装Consul包

打开命令行并运行以下命令创建一个新的 Web API 项目:

dotnet new webapi -n ConsulDemo
cd ConsulDemo
dotnet add package Consul
dotnet add package Microsoft.AspNetCore.HealthChecks.UI

二、配置 Consul 客户端

创建一个服务来注册Web API 到 Consul。可以在 Program.cs 中进行配置

Consul 客户端只能接受一个地址,因此需要实现一个逻辑,在连接失败时轮询下一个 Consul 服务器。这里是一个简单的策略,尝试多个 Consul 服务器地址:

(一) ConsulHelper.cs

using Consul;

public class ConsulHelper
{
    private readonly string[] _consulServers;

    public ConsulHelper(string[] consulServers)
    {
        _consulServers = consulServers;
    }

    // 连接到 Consul 并返回连接的 ConsulClient
    public async Task<ConsulClient> ConnectConsulAsync()
    {
        foreach (var server in _consulServers)
        {
            try
            {
                var consulClient = new ConsulClient(config =>
                {
                    config.Address = new Uri(server);
                });

                // 测试连接
                var services = await consulClient.Agent.Services();
                Console.WriteLine($"Connected to Consul at {server}");
                return consulClient;
            }
            catch (HttpRequestException)
            {
                Console.WriteLine($"Failed to connect to Consul at {server}, trying next...");
            }
        }

        throw new Exception("Failed to connect to any Consul servers.");
    }

    // 注册服务到 Consul
    public async Task RegisterServiceAsync(ConsulClient consulClient, string serviceId, string serviceName, string address, int port, string[] tags = null)
    {
        var registration = new AgentServiceRegistration()
        {
            ID = serviceId,
            Name = serviceName,
            Address = address,
            Port = port,
            Tags = tags ?? new[] { "api", serviceName },
            Check = new AgentServiceCheck
            {
                HTTP = $"http://{address}:{port}/health",
                Interval = TimeSpan.FromSeconds(10),
                Timeout = TimeSpan.FromSeconds(5)
            }
        };

        await consulClient.Agent.ServiceRegister(registration);
        Console.WriteLine($"Service {serviceName} registered with ID {serviceId}");
    }

    // 注销服务
    public async Task DeregisterServiceAsync(ConsulClient consulClient, string serviceId)
    {
        await consulClient.Agent.ServiceDeregister(serviceId);
        Console.WriteLine($"Service {serviceId} deregistered");
    }
}

(二) Program.cs

using Microsoft.Extensions.Diagnostics.HealthChecks;

var builder = WebApplication.CreateBuilder(args);

// 添加必要的服务
builder.Services.AddControllers();

// 添加健康检查服务
builder.Services.AddHealthChecks()
    .AddCheck("self", () => HealthCheckResult.Healthy("The service is healthy"));

// 创建应用
var app = builder.Build();

// Consul server 服务器集群地址
var consulServers = new[]
{
    "http://consul-server-1:8500",
    "http://consul-server-2:8500",
    "http://consul-server-3:8500"
};

// 也可以直接通过本地consul client 转发注册到 consul server//var consulServers = new[]
//{
// "http://127.0.0.1:8500",
//};

// 创建 ConsulHelper 实例
var consulHelper = new ConsulHelper(consulServers);

// 连接到 Consul 并注册服务
var serviceId = $"my-api-20240911";
var consulClient = await consulHelper.ConnectConsulAsync();
await consulHelper.RegisterServiceAsync(consulClient, serviceId, "my-api-service", "<本机ip>", 5048);

// 在应用关闭时注销服务
app.Lifetime.ApplicationStopping.Register(async () =>
{
    await consulHelper.DeregisterServiceAsync(consulClient, serviceId);
});

// 配置 HTTP 请求管道
app.MapControllers();
app.MapHealthChecks("/health");

// 启动应用
app.Run();

 

运行项目并查看Consul ui

三、客户端调用

(一) 创建控制台项目

使用 .NET CLI 创建控制台项目:

dotnet new console -n ConsulServiceDiscoveryConsole
cd ConsulServiceDiscoveryConsole
dotnet add package Consul

(二) 创建 ConsulServiceDiscovery 类

在控制台项目中创建一个 ConsulServiceDiscovery 类,用来从 Consul 获取已注册的服务。

ConsulServiceDiscovery.cs

using Consul;
using System;
using System.Linq;
using System.Threading.Tasks;

public class ConsulServiceDiscovery
{
    private readonly ConsulClient _consulClient;

    public ConsulServiceDiscovery(string consulAddress)
    {
        // 初始化 Consul 客户端
        _consulClient = new ConsulClient(config =>
                                         {
                                             config.Address = new Uri(consulAddress);
                                         });
    }

    // 获取服务实例的地址
    public async Task<Uri> GetServiceUriAsync(string serviceName, string tag = null)
    {
        // 查询 Consul 中的服务
        var queryResult = await _consulClient.Health.Service(serviceName, tag, passingOnly: true);

        // 选择一个健康的服务实例
        var service = queryResult.Response.FirstOrDefault();

        if (service == null)
        {
            throw new Exception($"Service {serviceName} not found in Consul.");
        }

        var address = service.Service.Address;
        var port = service.Service.Port;

        // 返回服务的 URI
        return new Uri($"http://{address}:{port}");
    }
}

(三) 更新 Program.cs

Program.cs 中使用 ConsulServiceDiscovery 来从 Consul 获取服务信息,并调用 Web API。

Program.cs

class Program
{
    static async Task Main(string[] args)
    {
        // Consul 服务器地址
        string consulAddress = "http://<consul地址>";  // 这里直接取其中一个,如需负载,可轮询或其他方式

        // 创建 ConsulServiceDiscovery 实例
        var serviceDiscovery = new ConsulServiceDiscovery(consulAddress);

        // 目标服务名称(注册到 Consul 中的服务名称)
        string serviceName = "my-api-service";  // 你注册到 Consul 的 Web API 服务名称

        try
        {
            // 获取 Web API 服务的地址
            var serviceUri = await serviceDiscovery.GetServiceUriAsync(serviceName);
            Console.WriteLine($"Discovered service at: {serviceUri}");

            // 使用 HttpClient 进行调用
            var httpClient = new HttpClient();
            string url = $"{serviceUri}health";
            var result = await httpClient.GetStringAsync(url);
            Console.WriteLine($"Service response: {result}");
            Console.ReadKey();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Service discovery failed: {ex.Message}");
        }
    }
}

返回Healthy 调用成功。

posted @ 2024-09-11 17:54  咸鱼翻身?  阅读(34)  评论(0编辑  收藏  举报