Dot-Net-Core

ocelot 配置文件中的環境變數

  • August 26, 2020

我有多個微服務可供客戶端通過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",
     "DownstreamScheme": "http",
     "DownstreamHostAndPorts": [
       {
         "Host": "identity-api",
         "Port": 80
       }
     ],
     "SwaggerKey": "Identity"
   },

我想要的是:

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

我能夠使用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"
   }
 }
} 

引用自:https://stackoverflow.com/questions/63421563