使用Docker部署Consul集群并由Ocelot调用

x33g5p2x  于5个月前 转载在 Docker  
字(4.8k)|赞(0)|评价(0)|浏览(232)

关于 consul 的介绍就不写了百度就行,我们直接开干。

一、部署consul集群

拉取consul的镜像

docker pull consul

然后部署consul容器

docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:latest agent -server -bootstrap-expect 2 -ui -bind='0.0.0.0' -client='0.0.0.0'

8500 http 端口,用于 http 接口和 web ui
8300 server rpc 端口,同一数据中心 consul server 之间通过该端口通信
8301 serf lan 端口,同一数据中心 consul client 通过该端口通信
8302 serf wan 端口,不同数据中心 consul server 通过该端口通信
8600 dns 端口,用于服务发现

-bbostrap-expect 2 : 集群至少两台服务器,才能选举集群 leader
-ui :运行 web 控制台
-bind : 监听网口, 0.0.0.0 表示所有网口,如果不指定默认为 127.0.0.1 ,则无法和容器通信
-client : 限制某些网口可以访问

-server :表示该节点是 server 节点,不声明的话默认为 client 节点,它们的不同是 server 节点持久化信息,但是 client 不持久化会转发给 server 节点,并且 server 节点会有 leader 节点进行健康检测和同步信息到其他 server 节点

然后我们获取该 consul1 容器的 ip ,使用如下语句

docker inspect --format '{{ .NetworkSettings.IPAddress }}' consul1

获取到了 172.17.0.5

然后我们再新建另一个 consul 容器,使用 join 来加入第一个 consul1 容器的集群

docker run --name consul2 -d -p 18500:8500 -p 18300:8300 -p 18301:8301 -p 18302:8302 -p 18600:8600 consul:latest agent -server -ui -bind='0.0.0.0' -client='0.0.0.0' -join 172.17.0.5

我就建两个节点能运行即可, server 一般建 3-5 个, client 没有上限,所以根据上面的语句自己建立即可。

然后我们访问地址 http://localhost:8500/ 可以进到控制界面。

 二、将服务注册到Consul中

为测试方便我们使用 -dev 参数允许启动一个 Consul 服务。

docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:latest agent -server -ui -bind='0.0.0.0' -client='0.0.0.0' -dev

我们新建一个项目,然后下载Consul包

Install-Package Consul

然后我们添加一个健康检查的接口

[Route("[controller]/[action]")]
    [ApiController]
    public class HealthController : Controller
    {
        [HttpGet("/healthCheck")]
        public IActionResult Check() => Ok("ok");
    }

之后我们在 appsetting.json 中配置我们的 Consul 参数,这些参数我们用来注册服务的一些信息,参数解释如下:

ServiceName :是服务的名称,同一个服务名的服务将会注册到同一个服务下的实例

ServiceIP :服务请求的主机地址

ServicePort :服务请求的端口

ServiceHealthCheck :服务健康检测接口地址,此处是 host.docker.internal 是因为 Consul 在容器内需要访问宿主主机运行的服务

AddressConsul 服务的请求地址

"Consul": {
    "ServiceName": "service-a",
    "ServiceIP": "127.0.0.1",
    "ServicePort": 5001,
    "ServiceHealthCheck": "http://host.docker.internal:5001/healthCheck",
    "Address": "http://127.0.0.1:8500"}

之后我们创建一个类名叫 ConsulOption ,用于使用过 Option 模式加载 appsetting.json 中我们配置的参数,用于注册

public classConsulOption
    {
        /// <summary>
        ///服务名称
        /// </summary>
        public string ServiceName { get; set; }
        /// <summary>
        ///服务IP
        /// </summary>
        public string ServiceIP { get; set; }
        /// <summary>
        ///服务端口
        /// </summary>
        public int ServicePort { get; set; }
        /// <summary>
        ///服务健康检查地址
        /// </summary>
        public string ServiceHealthCheck { get; set; }
        /// <summary>
        ///Consul 地址
        /// </summary>
        public string Address { get; set; }
    }

View Code

然后创建一个 Consul 服务注册类 ConsulBuilderExtensions ,对将本服务推送到 Consul 中去,具体的参数解释在代码注释中了

public static classConsulBuilderExtensions
    {
        public static IApplicationBuilder RegisterConsul(thisIApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption)
        {
            var consulClient = new ConsulClient(x =>{
                x.Address = newUri(consulOption.Address);
            });
            var registration = newAgentServiceRegistration()
            {
                ID =Guid.NewGuid().ToString(),
                Name = consulOption.ServiceName,//服务名
                Address = consulOption.ServiceIP, //服务绑定IP
                Port = consulOption.ServicePort, //服务绑定端口
                Check = newAgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
                    Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
                    HTTP = consulOption.ServiceHealthCheck,//健康检查地址
                    Timeout = TimeSpan.FromSeconds(5)
                }
            };
            //服务注册
consulClient.Agent.ServiceRegister(registration).Wait();
            //应用程序终止时,服务取消注册
lifetime.ApplicationStopping.Register(() =>{
                consulClient.Agent.ServiceDeregister(registration.ID).Wait();
            });
            returnapp;

        }
    }

最后我们注入本服务

builder.Services.AddSingleton(builder.Configuration.GetSection("Consul").Get<ConsulOption>());
//....
app.RegisterConsul(app.Lifetime, app.Services.GetRequiredService<ConsulOption>());

启动项目就能看到服务已经注册

Consul提供了http api可以让我们进行查询、注册、接触注册等操作

http://127.0.0.1:8500/v1/health/service/service-a?passing

 三、使用Ocelot调用

我们新建一个项目然后安装包

Install-Package Ocelot.Provider.Consul

然后注册服务

builder.Services.AddOcelot().AddPolly().AddConsul();

之后在配置文件中的 GlobalConfiguration 节点下添加如下参数,这是必须的如果没有指定主机 Host 和端口 Port 将会使用 Consul 默认的, Scheme 默认为 httpType 说明此服务发现由 Consul 提供

"ServiceDiscoveryProvider": {
    "Scheme": "http",
    "Host": "localhost",
    "Port": 8500,
    "Type": "Consul"}

然后我们设置路由,添加我们刚注册的服务,最好是配合负载均衡参数咯,我这里没写

"Routes": [
    {
      "DownstreamPathTemplate": "/{everything}",
      "DownstreamScheme": "http",
      "ServiceName": "service-a",
      "UpstreamPathTemplate": "/api/{everything}",
      "UpstreamHttpMethod": [ "Get", "Post"]
    }]

然后运行就可以看到结果了,需要注意的是请求是 http 还是 https 这些需要注意,我就卡在了这里很久,请求路径需要注意噢

最后, Ocelot 是每次请求都去 Consul 获取最新的服务,如果需要设置间隔多久去获取 Consul 的最新服务(可能会有微小的性能改进,但是不知道原有服务是否可用,可能会有错误的返回噢)可以如下设置:

"ServiceDiscoveryProvider": {
    "Host": "localhost",
    "Port": 8500,
    "Type": "PollConsul",
    "PollingInterval": 100}

相关文章

最新文章

更多