ocelot配置文件中的环境变量

问题描述

我有多个微服务,客户端可以通过Ocelot网关访问这些微服务。在配置文件中,有一些属性可以指定下游主机和端口。对于每个路由都必须这样做。

问题在于,如果服务的主机名或端口发生更改,我将不得不修改与此特定服务关联的每条路由。

因此,问题是,是否可以在ocelot.json配置文件中引入ENV变量?在那种情况下,我只需要修改一个ENV变量,所有关联的路由都会受到影响。

这是我当前的配置文件(我使用的是docker-compose,因此服务名称用作主机):

"Routes": [
    {
      "UpstreamPathTemplate": "/api/v1/signIn","DownstreamPathTemplate": "/api/v1/signIn","DownstreamScheme": "http","DownstreamHostAndPorts": [
        {
          "Host": "identity-api","Port": 80
        }
      ],"SwaggerKey": "Identity"
    },{
      "UpstreamPathTemplate": "/api/v1/validate","DownstreamPathTemplate": "/api/v1/validate",

我想要什么:

"Routes": [
    {
      "UpstreamPathTemplate": "/api/v1/signIn","DownstreamHostAndPorts": [
        {
          "Host": {SERVICE_HOST},"Port": {SERVICE_PORT}
        }
      ],

解决方法

我能够使用PostConfigure扩展方法来实现此缺失的功能。就我而言,我更喜欢将占位符配置放入Ocelot.json中,但是您可以更改代码以在IConfiguration中查找,而不是使用GlobalHosts

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration.File;

public static class FileConfigurationExtensions
{
    public static IServiceCollection ConfigureDownstreamHostAndPortsPlaceholders(
        this IServiceCollection services,IConfiguration configuration)
    {
        services.PostConfigure<FileConfiguration>(fileConfiguration =>
        {
            var globalHosts = configuration
                .GetSection($"{nameof(FileConfiguration.GlobalConfiguration)}:Hosts")
                .Get<GlobalHosts>();

            foreach (var route in fileConfiguration.Routes)
            {
                ConfigureRote(route,globalHosts);
            }
        });

        return services;
    }

    private static void ConfigureRote(FileRoute route,GlobalHosts globalHosts)
    {
        foreach (var hostAndPort in route.DownstreamHostAndPorts)
        {
            var host = hostAndPort.Host;
            if (host.StartsWith("{") && host.EndsWith("}"))
            {
                var placeHolder = host.TrimStart('{').TrimEnd('}');
                if (globalHosts.TryGetValue(placeHolder,out var uri))
                {
                    route.DownstreamScheme = uri.Scheme;
                    hostAndPort.Host = uri.Host;
                    hostAndPort.Port = uri.Port;
                }
            }
        }
    }
}

GlobalHosts类:

public class GlobalHosts : Dictionary<string,Uri> { }

用法:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddOcelot();
    services.ConfigureDownstreamHostAndPortsPlaceholders(Configuration);
}

Ocelot.json

{
  "Routes": [
    {
      "UpstreamPathTemplate": "/my-resource","UpstreamHttpMethod": [ "POST" ],"DownstreamPathTemplate": "/my/resource","DownstreamHostAndPorts": [
        {
          "Host": "{MyService}"
        }
      ]
    }
  ],"GlobalConfiguration": {
    "BaseUrl": "https://localhost:5000","Hosts": {
      "MyService": "http://localhost:3999"
    }
  }
}