Ocelot基于Consul服务发现

 

Ocelot基于Consul服务发现

前言

上章节介绍了将WebAPI接口服务注册到Consul中,这节介绍.NET Core平台下Ocelot基于Consul的服务发现。

环境:Win10+VS2022 +.NET5.0 + Ocelot17.0.0.0 + Consul 1.6.1.1

服务发现

Ocelot 允许您指定服务发现提供程序,并将使用它来查找 Ocelot 将请求转发到的下游服务的主机和端口。目前这仅在 GlobalConfiguration 部分中受支持,这意味着相同的服务发现提供程序将用于您在路由级别指定 ServiceName 的所有路由。

Consul

需要做的第一件事是在 Ocelot 中安装提供 Consul 支持的 NuGet 包。

 Install-Package Ocelot.Provider.Consul

 

然后将以下内容添加到您的 ConfigureServices 方法中。

s.AddOcelot()

 .AddConsul();

 

GlobalConfiguration 中需要以下内容。Provider 是必需的,如果您不指定主机和端口,则将使用 Consul 默认值。

请注意 Scheme 选项默认为 HTTP。它被添加到这个PR中。它默认为 HTTP 以不引入重大更改。

"ServiceDiscoveryProvider": {

    "Scheme": "https",

    "Host": "localhost",

    "Port": 8500,

    "Type": "Consul"

}

 

将来我们可以添加一个允许特定路由配置的功能。

为了告诉 Ocelot Route 是为其主机和端口使用服务发现提供程序,您必须添加您希望在向下游发出请求时使用的 ServiceName 和负载均衡器。目前,Ocelot 有一个可以使用的 RoundRobin LeastConnection 算法。如果没有指定负载均衡器,Ocelot 将不会对请求进行负载均衡。

{

    "DownstreamPathTemplate": "/api/posts/{postId}",

    "DownstreamScheme": "https",

    "UpstreamPathTemplate": "/posts/{postId}",

    "UpstreamHttpMethod": [ "Put" ],

    "ServiceName": "product",

    "LoadBalancerOptions": {

        "Type": "LeastConnection"

},

}

 

设置完成后,Ocelot 将从服务发现提供者那里查找下游主机和端口,并在任何可用服务之间实现负载平衡请求。

很多人要求我实现一个功能,即 Ocelot 轮询 Consul 以获取最新的服务信息,而不是每个请求。如果您想轮询 Consul 以获取最新服务而不是每个请求(默认行为),那么您需要设置以下配置。

"ServiceDiscoveryProvider": {

    "Host": "localhost",

    "Port": 8500,

    "Type": "PollConsul",

    "PollingInterval": 100

}

 

轮询间隔以毫秒为单位,告诉 Ocelot 多久调用一次 Consul 以更改服务配置。

请注意这里有权衡。如果您轮询 ConsulOcelot 可能不会根据您的轮询间隔知道服务是否已关闭,并且您可能会遇到比您获得每个请求的最新服务更多的错误。这实际上取决于您的服务有多不稳定。我怀疑这对大多数人来说很重要,轮询可能会比每个请求调用 Consul(作为 Sidecar 代理)带来微小的性能改进。如果您正在调用远程 Consul 代理,那么轮询将是一个很好的性能改进。

您的服务需要添加到 Consul 中,如下所示(C# 风格,但希望这是有意义的)……唯一需要注意的是不要在地址字段中添加 http https

"Service": {

       "ID": "some-id",

       "Service": "some-service-name",

       "Address": "localhost",

       "Port": 8080

   }

 

 

ACL 令牌

如果您将 ACL Consul Ocelot 一起使用,则支持添加 X-Consul-Token 标头。为了使它起作用,您必须在下面添加附加属性。

"ServiceDiscoveryProvider": {

    "Host": "localhost",

    "Port": 8500,

    "Token": "footoken",

    "Type": "Consul"

}

 

Ocelot 会将此令牌添加到它用来发出请求的 Consul 客户端,然后用于每个请求。

 

项目实现

4.1 新建Ocelot网关项目

在上节的项目中再新建一个Ocelot网关项目,命名为“Yak.Ocelot.Gateway”,修改启动端口为“5000”。

 "Yak.Ocelot.Gateway": {

      "commandName": "Project",

      "dotnetRunMessages": "true",

      "launchBrowser": true,

      "applicationUrl": "http://localhost:5000",

      "environmentVariables": {

        "ASPNETCORE_ENVIRONMENT": "Development"

      }

 

4.2 添加OcelotOcelotConsul依赖

添加依赖后,Yak.Ocelot.Gateway项目文件下添加了下面代码。

 <ItemGroup>

    <PackageReference Include="Ocelot" Version="17.0.0" />

    <PackageReference Include="Ocelot.Provider.Consul" Version="17.0.0" />

  </ItemGroup>

 

4.3 把服务注册到Consul

  1. 项目中添加Consul 注册发现相关参数类ConsulOption

/// <summary>

    /// Consul 注册发现相关参数

    /// </summary>

    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; }

    }

 

  1. 添加Consul注册发现扩展类ConsulBuilderExtensions

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;

        }

    }

 

  1. 添加ocelot配置文件,ocelot.json文件。

{

  "Routes": [

    {

      "DownstreamPathTemplate": "/WeatherForecast",

      "DownstreamScheme": "http",

      "ServiceName": "service-a",

      "UseServiceDiscovery": true,

      "UpstreamPathTemplate": "/Weather",

      "UpstreamHttpMethod": [ "Get" ],

      "LoadBalancerOptions": {

        "Type": "RoundRobin"

      }

    }

  ],

  "GlobalConfiguration": {

    "BaseUrl": "http://localhost:5000"

  }

}

 

  1. 修改Startup

   public void ConfigureServices(IServiceCollection services)

        {

services.AddControllers();

services

                .AddOcelot()

                .AddConsul();

                 }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption)

        {

            .........

app.UseEndpoints(endpoints =>

            {

                endpoints.MapGet("/", async context =>

                {

                    await context.Response.WriteAsync("我是Ocelot网关!");

                });

            });

            // 注册

             app.UseOcelot().Wait();

            ...........

        }

 

4.4 启动Consul

这里是Win10系统,下载相应的Consul后,在文件夹下创建启动BAT文件用于启动Consul,双击启动。

4.5 服务发现

启动Yak.Ocelot.Api”项目,查看到服务已经注册到Consul中。

 

 

 

 

 

4.6 调试

运行网关项目Yak.Ocelot.Gateway”,通过访问网关地址:http://localhost:5000/Weather访问WebAPI天气接口服务。

 

 

 

 

 

 

总结

通过Consul服务发现功能,先将接口服务注册到Consul中,然后结合Ocelot,在不需要配置下游接口服务地址和端口情况下,直接就可以访问接口服务了,省去了配置接口服务的麻烦。

鸣谢

https://ocelot.readthedocs.io/en/latest/features/servicediscovery.html

源码

https://github.com/yandaniugithub/NETCore/tree/main/Yak.Ocelot.Demo

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-04-06 21:22  春光牛牛  阅读(283)  评论(0编辑  收藏  举报