You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Service Bus事件处理中Scoped服务使用问题求助

解决Azure Service Bus单例处理器使用Scoped服务及ITokenAcquisition的问题

核心问题分析

单例的ServiceBus事件处理器无法直接注入Scoped服务,且后台消息处理场景下无HttpContext支撑,导致依赖HttpContext的ITokenAcquisition出现服务提供方已释放的错误。以下是具体解决方案:


解决方案步骤

1. 通过IServiceScopeFactory在单例处理器中创建作用域

修改单例的IServiceBusTopicSubscription实现类,注入IServiceScopeFactory,在每次消息处理时创建独立的服务作用域,在作用域内解析Scoped服务:

public class ServiceBusTopicSubscription : IServiceBusTopicSubscription
{
    private readonly IServiceScopeFactory _scopeFactory;

    public ServiceBusTopicSubscription(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public async Task ProcessMessageAsync(ProcessMessageEventArgs args)
    {
        // 为当前消息处理创建独立作用域
        using var scope = _scopeFactory.CreateScope();
        var processData = scope.ServiceProvider.GetRequiredService<IProcessData>();
        
        // 执行消息处理逻辑
        await processData.HandleMessageAsync(args.Message);
        
        // 标记消息处理完成
        await args.CompleteMessageAsync(args.Message);
    }
}

2. 调整ITokenAcquisition的使用方式(适配后台无HttpContext场景)

后台消息处理无HttpContext,需改用客户端凭据模式获取令牌,避免依赖HttpContext的方法。修改ExternalRestSystem的实现:

public class ExternalRestSystem : IExternalRestSystem
{
    private readonly ITokenAcquisition _tokenAcquisition;
    private readonly HttpClient _httpClient;

    public ExternalRestSystem(ITokenAcquisition tokenAcquisition, HttpClient httpClient)
    {
        _tokenAcquisition = tokenAcquisition;
        _httpClient = httpClient;
    }

    public async Task SendToApiAsync(string payload)
    {
        // 使用客户端凭据流获取令牌,替换为目标API的范围(格式:API应用ID URI + /.default)
        var tokenResult = await _tokenAcquisition.AcquireTokenForClient(
            new[] { "https://your-target-api.azurewebsites.net/.default" })
            .ExecuteAsync();

        _httpClient.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", tokenResult.AccessToken);
        
        await _httpClient.PostAsJsonAsync("https://your-target-api.azurewebsites.net/api/endpoint", payload);
    }
}

3. 完善服务注册配置

在Program.cs中确保正确注册服务及Azure AD客户端凭据:

// 配置Azure AD认证及下游API令牌获取
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

// 注册HttpClient及业务服务
builder.Services.AddHttpClient<IExternalRestSystem, ExternalRestSystem>();
builder.Services.AddSingleton<IServiceBusTopicSubscription, ServiceBusTopicSubscription>();
builder.Services.AddScoped<IProcessData, ProcessData>();
builder.Services.AddScoped<IExternalRestSystem, ExternalRestSystem>();

关键注意事项

  • 每个消息处理创建独立作用域,避免并发场景下的Scoped服务冲突
  • AcquireTokenForClient所需的API范围需与Azure AD应用注册中配置的权限一致
  • 确保Azure AD应用注册已配置有效的客户端凭据(密钥或证书),并被授予目标API的访问权限

内容的提问来源于stack exchange,提问作者swankyprogramming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:45:39