我正在使用 Ocelot 和 API 网关以及 Consul 和服务发现。 我正在 Consul 中使用动态名称注册服务,例如:service.name.1234 和 service.name.5678
此服务是静态的,根本不打算扩展
由于我正在使用 Ocelot,我希望能够将请求路由到所需的服务,但由于名称是动态的,我需要使用查询字符串参数作为服务名称
示例:http://myapp.com/service/1234 应该重定向到名为 service.name.1234 的容器
有什么方法可以同时使用这两种产品来实现这一目标吗?或者也许其他产品?
谢谢你
我一直在寻找相同的解决方案,但在 GitHub 上只找到了一条评论,它对我帮助很大
因此,您需要创建自定义中间件来重写 Ocelot 的 DownstreamRoute:
public static async Task InvokeAsync(HttpContext httpContext, Func<Task> next)
{
var downstreamRoute = httpContext.Items.DownstreamRoute();
var yourServiceName = //get query string parameter from httpContext;
//rewrite any parameter that you want
httpContext.Items.UpsertDownstreamRoute(
new DownstreamRoute(
downstreamRoute.Key,
downstreamRoute.UpstreamPathTemplate,
downstreamRoute.UpstreamHeadersFindAndReplace,
downstreamRoute.DownstreamHeadersFindAndReplace,
downstreamRoute.DownstreamAddresses,
tenantServiceName,
...
));
}
然后在 Startup.cs 中调用它:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// some other code
var configuration = new OcelotPipelineConfiguration
{
PreQueryStringBuilderMiddleware = async (ctx, next) =>
{
await RouteContextRetrieverMiddleware.InvokeAsync(ctx, next);
await next.Invoke();
}
};
app.UseOcelot(configuration).GetAwaiter().GetResult();
}
我遇到了同样的问题,我参考了你的代码,并遇到了与 Praveen Valavan 相同的问题。
查看 Ocelots 源代码后,似乎它在内部将
LoadBalancerKey
缓存在 downStreamRoute
中。这就是为什么它只适用于第一个请求的原因。 (因为您的路线模板保持不变)。
您可以通过使 LoadBalancerKey
动态化来解决这个问题。
public static async Task InvokeAsync(HttpContext httpContext, Func<Task> next)
{
try
{
var matchingDownstreamRoute = httpContext.Items.DownstreamRoute();
var version = httpContext.Items?.DownstreamRouteHolder()?.TemplatePlaceholderNameAndValues[0].Value;
var newDownstreamRoute = new DownstreamRoute(
matchingDownstreamRoute.ServiceName + "-" + version,
matchingDownstreamRoute.LoadBalancerKey.Replace("{version}",version)
);
httpContext.Items.UpsertDownstreamRoute(newDownstreamRoute);
}
catch (System.Exception ex)
{
throw;
}
}