关于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 ui8300 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 class ConsulOption
    {
        /// <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 class ConsulBuilderExtensions
    {
        public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption)
        {
            var consulClient = new ConsulClient(x =>
            {
                x.Address = new Uri(consulOption.Address);
            });
            var registration = new AgentServiceRegistration()
            {
                ID = Guid.NewGuid().ToString(),
                Name = consulOption.ServiceName,// 服务名
                Address = consulOption.ServiceIP, // 服务绑定IP
                Port = consulOption.ServicePort, // 服务绑定端口
                Check = new AgentServiceCheck()
                {
                    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();
            });
            return app;

        }
    }

最后我们注入本服务

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
}

 

作者:|以往清泉|,原文链接: https://www.cnblogs.com/xwc1996/p/17233311.html

文章推荐

如何在 Python 中实现遗传算法

关于 Bash 脚本中 Shebang 的趣事

深入理解python虚拟机:调试器实现原理与源码分析

如何在 .NET Core WebApi 中处理 MultipartFormDataContent

使用 Azure OpenAI 打造自己的 ChatGPT

Asp-Net-Core开发笔记:使用RateLimit中间件实现接口限流

读懂React原理之调和与Fiber

滴滴前端高频vue面试题(边面边更)

Java零基础学习的点点建议

聊聊OOP中的设计原则以及访问者模式

如何简单、高效的进行留存和漏斗分析

聊聊如何实现一个带幂等模板的Kafka消费者