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


    关于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 class ConsulOption
        {
            /// 
            /// 服务名称
            /// 
            public string ServiceName { get; set; }
            /// 
            /// 服务IP
            /// 
            public string ServiceIP { get; set; }
            /// 
            /// 服务端口
            /// 
            public int ServicePort { get; set; }
            /// 
            /// 服务健康检查地址
            /// 
            public string ServiceHealthCheck { get; set; }
            /// 
            /// Consul 地址
            /// 
            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());
    //....
    app.RegisterConsul(app.Lifetime, app.Services.GetRequiredService());

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

    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
    }
    复制代码

     

  • 相关阅读:
    基于Eigen的椭圆拟合
    面试官问我new Vue阶段做了什么?
    df命令:显示系统上可使用的磁盘空间
    高额补贴!武汉市科技型企业保证保险贷款补贴申报条件、流程和材料
    金蝶云星空表单插件实现父窗体打开子窗体,并携带参数到子窗体
    【QT】点击按钮弹出对话框的注意事项
    linux文件锁的使用
    【程序人生】27岁,又是一个新的起点
    C#的基于.net framework的Dll模块编程(二) - 编程手把手系列文章
    Linux系统运维脚本:shell脚本查看一定网段范围在线网络设备的ip地址和不在线的网络设备的数量(查看在线和不在线网络设备)
  • 原文地址:https://www.cnblogs.com/xwc1996/p/17233311.html