1. 拉取镜像

docker pull consul

2. 部署及运行容器

注意:每一个容器都可以单独部署UI界面,按需要来。

#启动第1个Server节点,集群要求要有3个Server,将容器8500端口映射到主机8900端口,同时开启管理界面

docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui

#启动第1个consul后,查看一下其IP是多少:
docker inspect -f '{{.NetworkSettings.IPAddress}}' consul1(服务器名称)

#我的环境查到的IP是172.17.0.6,因此下面都要加入这个IP地址的群集。
 
#启动第2个Server节点,并加入集群
docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.6
 
#启动第3个Server节点,并加入集群
docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.6
 
#启动第4个Client节点,并加入集群
docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.6

3.consul服务注册及治理

先写一个扩展方法:

using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoreWebMVC.Extension
{
    public static class AppBuilderExtensions
    {
        public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ServiceEntity serviceEntity)
        {
            var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}"));//请求注册的 Consul 地址
            var httpCheck = new AgentServiceCheck()
            {
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
                Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔
                HTTP = $"http://{serviceEntity.IP}:{serviceEntity.Port}/api/health",//健康检查地址
                Timeout = TimeSpan.FromSeconds(5)
            };

            // Register service with consul
            var registration = new AgentServiceRegistration()
            {
                Checks = new[] { httpCheck },
                ID = Guid.NewGuid().ToString(),
                Name = serviceEntity.ServiceName,
                Address = serviceEntity.IP,
                Port = serviceEntity.Port,
                Tags = new[] { $"urlprefix-/{serviceEntity.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别
            };

            consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起)
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册
            });

            return app;
        }
    }
}

写一个心跳检测接收的API:

namespace CoreWebAPI.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class HealthController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            return Ok("ok, consul~~!");
        }
    }
}

然后,在Startup.cs中的Configure方法中加入注册的相关代码:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)
{
	........
	
    // consul配置
    ServiceEntity serviceEntity = new ServiceEntity
    {
        IP = Configuration["Consul:WebIP"],
        Port = Convert.ToInt32(Configuration["Consul:WebPort"]),
        ServiceName = Configuration["Consul:ConsulServiceName"],
        ConsulIP = Configuration["Consul:ConsulIP"],
        ConsulPort = Convert.ToInt32(Configuration["Consul:ConsulPort"])
    };
    app.RegisterConsul(lifetime, serviceEntity);
}

// 实体类
public class ServiceEntity
{
    public string IP { get; set; }
    public int Port { get; set; }
    public string ServiceName { get; set; }
    public string ConsulIP { get; set; }
    public int ConsulPort { get; set; }
}

修改appsettings.json配置文件,加入以下配置:

"Consul": {
  "ConsulIP": "192.168.107.128",
  "ConsulPort": "8900",
  "ConsulServiceName": "testconsul_master",
  "WebIP": "192.168.237.1",
  "WebPort": "8001"
}

参照之前的docker部署.net5站点,运行网站后,即可在consul的UI站点中看到增加了一个实例(instance),如下图:

docker微服务 架构图 docker微服务治理_consul

4. 服务的发现及消费

这块非常简单,直接上测试代码:

StringBuilder sb = new StringBuilder();

using (var consulClient = new Consul.ConsulClient(client =>
client.Address = new Uri("http://192.168.107.128:8900")
))
{
    var services = consulClient.Agent.Services().Result.Response;
    foreach (var service in services.Values)
    {
        sb.Append($"{service.Address}, {service.ID}, {service.Port}, {service.Service},");
    }
}
return $"consul: {sb.ToString()}";

服务已经全部取出来了,可以写一个随机算法,随机的消费服务。
用Postman测试,返回结果:

consul: 192.168.237.1, 40f468e0-7ce1-431a-9004-fd6f07b07b5d, 8001, testconsul_master,192.168.107.128, bd34e09b-c978-4acb-b433-4cd76b96b676, 8002, testconsul_master,