OpenFeature 标准在 ABP vNext 的落地

🚀 OpenFeature 标准在 ABP vNext 的落地



0. 摘要(TL;DR)✨

在 ABP vNext(.NET 8)中接入 OpenFeature .NET SDK,用统一的评估 API 读取特性开关;后端通过 Provider 对接 flagd / LaunchDarkly / Flipt 等系统,实现可插拔、零侵入
本方案覆盖:多租户上下文tenantId/userId/plan/region/targetingKey)、热更新/灰度Polly v8 韧性(超时/重试/断路/回退)+ 分布式缓存事件与可观测性(Hook/Tracking/OTel),并提供可复现的最小代码与 flags.json/Docker 配置。🧪

🗺️ 架构总览

ABP vNext 应用
flag def/targeting
可替换
可替换
Controller / AppService
IFeatureService 门面
SafeFeatureService (Polly+Cache)
OpenFeature Client
Provider 可插拔
flagd
LaunchDarkly
Flipt

1. 为什么选 OpenFeature 🔧

  • 统一 API,后端可插拔:业务只依赖 OpenFeature;更换平台仅替换 Provider。

  • 分工明确

    • 运行时评估/实验/跨生态 → OpenFeature(业务读开关)。
    • 治理/权限/后台配置 → ABP Feature(IFeatureChecker[RequiresFeature])。
  • 生态:开源 flagd(轻量、JsonLogic 规则、确定性分桶)、LaunchDarkly(成熟 SaaS)、Flipt(开源自托管)。🎯


2. 工程脚手架与依赖 📦

目标:.NET 8 + ABP vNext(ASP.NET Core)

dotnet add package OpenFeature
dotnet add package OpenFeature.DependencyInjection    # 实验性
dotnet add package OpenFeature.Hosting                # 实验性
dotnet add package OpenFeature.Contrib.Providers.Flagd
dotnet add package Polly                              # v8
dotnet add package Scrutor                            # 用于 services.Decorate 装饰器

🔔 提示:OpenFeature.DependencyInjection / OpenFeature.Hosting实验性集成,升级需关注变更说明。


3. ABP 集成设计(DI & 请求级 Transaction Context)🏗️

3.1 Program.cs(最小可运行骨架)

using OpenFeature;
using OpenFeature.DependencyInjection.Providers.Flagd;
using Volo.Abp;
using Volo.Abp.Modularity;

var builder = WebApplication.CreateBuilder(args);

// 1) OpenFeature + flagd Provider(托管生命周期)
builder.Services.AddOpenFeature(cfg =>
{
   
   
    cfg.AddHostedFeatureLifecycle() // 实验性:由宿主管理 Provider 的初始化/关闭
       .AddFlagdProvider(o =>
       {
   
   
           // 可用配置或环境变量 FLAGD_HOST/FLAGD_PORT
           o.Host = builder.Configuration["Flagd:Host"] ?? "localhost";
           o.Port = int.Parse(builder.Configuration["Flagd:Port"] ?? "8013");
       });
});

// 2) Transaction Context 传播器(基于 AsyncLocal)
Api.Instance.SetTransactionContextPropagator(new AsyncLocalTransactionContextPropagator());

// 3) 请求中间件:构造/设置/清理 EvaluationContext
builder.Services.AddTransient<OpenFeatureContextMiddleware>();

// 4) 业务门面与装饰器(Scoped,避免把 Scoped 依赖注入到单例)
builder.Services.AddScoped<IFeatureService, FeatureService>();
builder.Services.Decorate<IFeatureService, SafeFeatureService>(); // 叠加韧性与缓存

var app = builder.Build();
app.UseMiddleware<OpenFeatureContextMiddleware>(); // 放在认证之后更佳
app.MapGet("/", () => "ok");
app.Run();

3.2 请求中间件(设置并清理上下文)

using Volo.Abp.MultiTenancy;
using Volo.Abp.Users;

public class OpenFeatureContextMiddleware : IMiddleware
{
   
   
    private readonly ICurrentTenant _tenant;
    private readonly ICurrentUser _user;
    private readonly ILogger<OpenFeatureContextMiddleware> _logger;

    public OpenFeatureContextMiddleware(ICurrentTenant tenant, ICurrentUser user, ILogger<OpenFeatureContextMiddleware> logger)
    {
   
   
        _tenant = tenant;
        _user = user;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
    {
   
   
        var tenantId = _tenant.Id?.ToString() ?? "host";
        var userId   = _user.Id?.ToString() ?? "anonymous";
        var region   = ctx.Request.Headers["X-Region"].FirstOrDefault() ?? "ap-sg";
        var plan     = ctx.Request.Headers["X-Plan"].FirstOrDefault() ?? await ResolveTenantPlanAsync(_tenant);

        // targetingKey:稳定分桶键(建议:tenantId:userId)
        var evalCtx = EvaluationContext.Builder()
            .Set("tenantId", tenantId)
            .Set("userId",   userId)
            .Set(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kookoos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值