06_NET中使用Consul(服务发现)

官网:Consul by HashiCorp 

中文文档:Consul 中文文档 | Consul 中文文档 (gitbook.io)

安装Consul

window安装:Install | Consul | HashiCorp Developer

1. 选择windows x64 版本(64bit)
2. 进入下载好的文件夹中,打开powershell ,执行命令,启动服务端代理

consul.exe agent -dev

3. 浏览器输入:http://IP:8500/出现ConsulWeb界面就表示成功了

-dev 表示开发模式,生产环境下不建议使用,因为它不会保存任何状态
-server 生产环境下可使用

 

Docker 安装:

docker pull consul # 默认拉取latest
docker pull consul:1.15.4 # 拉取指定版本

安装并运行

docker run -d -p 8500:8500 --restart=always --name=consul consul agent -server - bootstrap -ui -node=1 -client='0.0.0.0'

agent: 表示启动 Agent 进程。
server:表示启动 Consul Server 模式
client:表示启动 Consul Cilent 模式。
bootstrap:表示这个节点是 Server-Leader ,每个数据中心只能运行一台服务器。技术角度上讲Leader 是通过 Raft 算法选举的,但是集群第一次启动时需要一个引导 Leader,在引导群集后,建议不要使用此标志。
ui:表示启动 Web UI 管理器,默认开放端口 8500,所以上面使用 Docker 命令把 8500 端口对外开放。
node:节点的名称,集群中必须是唯一的,默认是该节点的主机名。
client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
join:表示加入到某一个集群中去。 如:-json=192.168.0.11。

 

使用Consul:

安装包:Consul.AspNetCore

服务端

新建一个WebApi项目:Consul.ServiceA

修改appsettings.json配置文件

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Consul": {
    "HostAddress": "http://localhost:8500", 
    "ServiceAddress": "localhost",
    "Port": 5011,
    "ServerName": "Consul.ServiceA"
  }
}

HostAddress:Consul地址;   ServiceAddress:服务地址; Port:端口;  ServerName:服务名称

添加映射类

public class ConsulOption
{
    public string HostAddress { get; set; }
    public string ServiceAddress { get; set; }
    public int Port { get; set; }
    public string ServerName { get; set; }
}

 

添加扩展类

public static class ConsulServiceExtension
{
    public static IServiceCollection AddConsulService(this IServiceCollection services, IConfiguration configuration )
    {
        //获取配置文件信息
        var consulSection = configuration.GetSection("Consul");
        services.Configure<ConsulOption>(consulSection);
        var consulOption = consulSection.Get<ConsulOption>();

        //添加consul地址
        services.AddConsul(p =>
        {
            p.Address = new Uri(consulOption.HostAddress);
        });

        //注册consul
        services.AddConsulServiceRegistration(p =>
        {
            p.ID = Guid.NewGuid().ToString();
            p.Name = consulOption.ServerName;
            p.Address = consulOption.ServiceAddress;
            p.Port = consulOption.Port;
            
            // 健康检查
            p.Check = new()
            {
                // 1. 如果服务不可用(健康检查失败)的情况下,多久将当前服务移除
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                // 2. 健康检查间隔时间
                Interval = TimeSpan.FromSeconds(10),
                // 3. 健康检查地址(心跳地址)
                HTTP = $"http://{p.Address}:{p.Port}/health"
                // 4. 超时时间
                ,Timeout = TimeSpan.FromSeconds(5)
            };
        });

        return services;
    }
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddSwaggerGen();
builder.Services.AddConsulService(builder.Configuration);
var app = builder.Build();

app.UseSwagger();
app.UseSwaggerUI();

app.UseAuthorization();

app.MapControllers();

app.Run();

 

添加HealthController控制器

[ApiController]
[Route("[controller]")]
public class HealthController:ControllerBase
{

    [HttpGet]
    public IActionResult Check()
    {
        return Ok($"进行心跳检测:{DateTime.Now}");
    }
    
}

 

客户端:

新建一个webApi项目:Consul.Client

配置和服务端一致;appsettings.json的配置要记得修改;

 

-----------------------------------------------------漂亮的分割线-------------------------------------------------------------------------

测试:

服务端Consul.ServiceA添加一个控制器用于测试

[Route("[controller]/[action]")]
[ApiController]
public class ProductController:ControllerBase
{
    [HttpGet]
    public IActionResult GetProduct()
    {
        List<ProductInfo> list = new()
        {
            new() {Id = 1, Name = "商品1"},
            new() {Id = 2, Name = "商品2"}
        };
        return Ok(list);
    }
}

 

客户端Consul.Client添加一个控制器ClientController 去调用服务端

[Route("[controller]/[action]")]
[ApiController]
public class ClientController:ControllerBase
{
    private readonly IConsulClient _consulClient;

    public ClientController(IConsulClient consulClient)
    {
        _consulClient = consulClient;
    }

    [HttpGet]
    public async Task<IActionResult> GetProductByClient()
    {
        var instanceList = (await _consulClient.Catalog.
            Service("Consul.ServiceA")).Response;
        //随机获取一个服务
        var instance = instanceList[new Random().Next(instanceList.Length)];

        using HttpClient client = new();
        var json = await client.GetStringAsync($"http://{instance.ServiceAddress}:{instance.ServicePort}/Product/GetProduct");
        var result = JsonConvert.DeserializeObject<List<ProductInfo>>(json);

        return Ok(result);
    }
}

 

-----------------------------------------------------漂亮的分割线-------------------------------------------------------------------------

添加多个服务端(集群)

配置和Consul.ServiceA也是一样的,appsettings.json的配置要记得修改

"Consul": {
    "HostAddress": "Consul地址", 
    "ServiceAddress": "服务端地址",
    "Port": 服务端口,
    "ServerName": "这里的名称都要一样"
  }

 

posted @ 2024-04-16 10:59  野码  阅读(100)  评论(0编辑  收藏  举报