×

ASP.NET Core 实现 cluster-specific API

独孤求败 独孤求败 发表于2026-06-20 22:32:12 浏览34 评论0

抢沙发发表评论

ASP.NET Core 实现 cluster-specific API

Intro

前段时间我们一个新的服务里有有一些 API 只想在某个 k8s 集群里可以访问,其他集群里不可以访问,因为关系比较密切又不想拆成两个服务,所以就像实现某些 API 只在特定集群访问,我们的 openapi 文档上也想实现类似的过滤避免别人在 OpenAPI 文档上看到

Sample

新的服务是基于 .NET 10 是实现的,整体比较简单 API 都是通过 Minimal API 的实现的,OpenAPI 通过 ASP.NET 10 里内置的 OpenAPI 支持和 Scalar 来实现 UI

我们会在服务部署到我们 k8s 集群时通过 configmap 注入到服务的环境变量里,可以通过环境变量获取当前 cluster , 我们以 AppSettings__Cluster 环境变量为例,我们来看一下实现的效果

central cluster 的情况, central-0


图片
`api-endpoint-central`
图片
`openapi-central`

其他 cluster 的情况, catalog-0


图片
`api-response-non-central`
图片
`open-api-non-central`

Implement

对于 API 的实现比较简单,可以实现一个 IEndpointFilter 来实现,在不是 central enable 的情况下返回 NotFound


public
 class CentralClusterOnlyFilter : IEndpointFilter
{
    public
 static readonly CentralClusterOnlyFilter Instance = new();

    public
 static bool Enabled { get; } = Environment.GetEnvironmentVariable("AppSettings__Cluster")
        ?.Contains("central") == true;

    private CentralClusterOnlyFilter() { }

    public ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        return
 Enabled 
            ? next(context) 
            : ValueTask.FromResult<object?>(Results.NotFound());
    }
}

对于 OpenAPI 文档,可以通过 AddMetadata 给 Endpoint 添加一个 Metadata 然后再通过 OpenApiOption 中的 ShouldInclude 来将不希望展示的 API 给排除在外,可以定义一个 IEndpointConventionBuilder 的扩展方便使用,实现如下:


public
 static class EndpointExtension
{
    extension<TBuilder>(TBuilder endpoints) where TBuilder : IEndpointConventionBuilder
    {
        public TBuilder CentralClusterOnly()
        {
            endpoints
                .AddEndpointFilter(CentralClusterOnlyFilter.Instance)
                .WithMetadata(CentralClusterOnlyFilter.Instance)
                ;
            return
 endpoints;
        }
    }
}

针对需要配置的 API endpoint 添加 CentralClusterOnly() 即可

app.MapGet("/central-endpoint", () => Results.Ok())
    .CentralClusterOnly();

再来自定义一下 OpenAPI 的选项,通过 EndpointMetadata 来判断是否指定了 CentralClusterOnly 如果指定了,则应该仅在 Enable 的情况下包含在 OpenAPI 文档中

builder.Services.AddOpenApi(options =>
{
    options.ShouldInclude = d =>
    {
        var
 filter = d.ActionDescriptor.EndpointMetadata.OfType<CentralClusterOnlyFilter>().FirstOrDefault();
        if
 (filter is null)
        {
            return
 true;
        }
        return
 CentralClusterOnlyFilter.Enabled;
    };
});

More

这个示例是基于 Cluster 来实现的,其实我们也可以根据其他的环境或配置等需要来实现,分享一下希望对大家有帮助


群贤毕至

访客