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

MassTransit服务器端出现IServiceProvider已释放异常,本地运行正常

问题:MassTransit应用服务器环境报IServiceProvider已释放异常,本地运行正常

异常堆栈

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at MassTransit.Configuration.RegistrationContext.GetService(Type serviceType) in /_/src/MassTransit/DependencyInjection/Configuration/RegistrationContext.cs:line 133
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.CreateScope(IServiceProvider provider)
   at MassTransit.DependencyInjection.BaseConsumeScopeProvider.GetScopeContext[TScopeContext,TPipeContext](TPipeContext context, Func`4 existingScopeContextFactory, Func`4 createdScopeContextFactory, Func`4 pipeContextFactory) in /_/src/MassTransit/DependencyInjection/DependencyInjection/BaseConsumeScopeProvider.cs:line 40
   at MassTransit.DependencyInjection.ConsumeScopeProvider.GetScope[TConsumer,T](ConsumeContext`1 context) in /_/src/MassTransit/DependencyInjection/DependencyInjection/ConsumeScopeProvider.cs:line 43
   at MassTransit.DependencyInjection.ScopeConsumerFactory`1.Send[TMessage](ConsumeContext`1 context, IPipe`1 next) in /_/src/MassTransit/DependencyInjection/DependencyInjection/ScopeConsumerFactory.cs:line 20
   at MassTransit.Middleware.ConsumerMessageFilter`2.MassTransit.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext`1 context, IPipe`1 next) in /_/src/MassTransit/Middleware/ConsumerMessageFilter.cs:line 48
   at MassTransit.Middleware.ConsumerMessageFilter`2.MassTransit.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext`1 context, IPipe`1 next) in /_/src/MassTransit/Middleware/ConsumerMessageFilter.cs:line 73
   at MassTransit.Middleware.TransactionFilter`1.Send(T context, IPipe`1 next) in /_/src/MassTransit/Middleware/TransactionFilter.cs:line 48
   at MassTransit.Middleware.RetryFilter`1.MassTransit.IFilter<TContext>.Send(TContext context, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 47

问题背景

  • 本地环境运行无异常,仅服务器环境触发该错误
  • 初始异常出现在自定义Dapper仓储,改用DapperIntegration库后问题仍存在
  • 基于RabbitMQ配置,包含Saga状态机、重试机制、事务过滤器

配置代码

public static void ConfigureMassTransit(IServiceCollection services, RabbitMqConfiguration rabbitConfig, RabbitMqQueueConfiguration queueConfig, string sagaConnectionString)
{
    services.AddMassTransit(x =>
    {
        x.AddConsumers(Assembly.GetExecutingAssembly());
        var entryAssembly = System.Reflection.Assembly.GetEntryAssembly();

        x.AddSagaStateMachine<CaseSagaStateMachine, CaseSagaState>()                
        .DapperRepository(sagaConnectionString)
        .Endpoint(e =>
        {
            e.Name = queueConfig.CaseServiceBus;
        });
        
        x.UsingRabbitMq((context, cfg) =>
        {

            cfg.Host(new Uri($"rabbitmq://{rabbitConfig.Host}/{rabbitConfig.VirtualHost}"), host =>
            {
                host.Username(rabbitConfig.UserName);
                host.Password(rabbitConfig.Password);
            });

            
            cfg.ReceiveEndpoint(queueConfig.CaseServiceBus, endPoint => //replace with our created queue
            {
                endPoint.UseMessageRetry(retry =>
                {
                    retry.Intervals(new[] { 1, 2, 4, 8, 16, 32 }.Select(t => TimeSpan.FromMinutes(t)).ToArray());
                });

                endPoint.UseTransaction(x =>
                {
                    x.Timeout = TimeSpan.FromSeconds(90);
                    x.IsolationLevel = IsolationLevel.ReadCommitted;
                });

                //endPoint.UseInlineFilter(async (context, next) =>
                //{
                //    var transactionOptions = new TransactionOptions
                //    {
                //        Timeout = TimeSpan.FromSeconds(120),
                //        IsolationLevel = IsolationLevel.ReadUncommitted,
                //    };


                //    using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions, TransactionScopeAsyncFlowOption.Enabled))
                //    {
                //        await next.Send(context).ConfigureAwait(false);
                //        scope.Complete();
                //    }
                //});
                endPoint.ConfigureSagas(context);
                endPoint.ConfigureConsumers(context);
            });

            cfg.PrefetchCount =  10;
        });
    });

    services.Configure<MassTransitHostOptions>(options =>
    {
        options.WaitUntilStarted = true;
        options.StartTimeout = TimeSpan.FromSeconds(30);
        options.StopTimeout = TimeSpan.FromMinutes(1);
    });
   
    services.AddSingleton<IHostedService, BusService>();

}

解决方案

1. 移除自定义BusService,依赖MassTransit内置托管服务

你手动注册了BusService作为IHostedService,但MassTransit已自带托管服务负责总线生命周期管理。自定义实现若存在提前释放服务提供者或总线的逻辑,会导致消费时无法创建有效作用域。

修复:删除services.AddSingleton<IHostedService, BusService>();代码,让MassTransit自带托管服务接管总线启动/停止。

2. 调整重试与事务过滤器的顺序

当前重试过滤器在事务过滤器之前,重试时可能导致事务作用域与服务作用域生命周期不匹配,引发资源释放问题。

修复:将事务过滤器移至重试过滤器之前,确保每次重试都创建新的事务和作用域:

cfg.ReceiveEndpoint(queueConfig.CaseServiceBus, endPoint =>
{
    endPoint.UseTransaction(x =>
    {
        x.Timeout = TimeSpan.FromSeconds(90);
        x.IsolationLevel = IsolationLevel.ReadCommitted;
    });

    endPoint.UseMessageRetry(retry =>
    {
        retry.Intervals(new[] { 1, 2, 4, 8, 16, 32 }.Select(t => TimeSpan.FromMinutes(t)).ToArray());
    });

    endPoint.ConfigureSagas(context);
    endPoint.ConfigureConsumers(context);
});

3. 验证Saga仓储与依赖服务的生命周期

服务器环境并发或资源回收策略更严格,若仓储或数据库连接生命周期配置错误,会提前释放资源。

修复建议:

  • 数据库连接注册为Scoped,避免单例实例被提前回收
  • 仓储类注册为Scoped或Transient,与消费作用域保持一致
  • 若需要,显式指定Saga仓储生命周期:
    x.AddSagaStateMachine<CaseSagaStateMachine, CaseSagaState>()                
      .DapperRepository(sagaConnectionString)
      .AddScoped() // 按需调整为Singleton/Transient
      .Endpoint(e =>
      {
          e.Name = queueConfig.CaseServiceBus;
      });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 11:57:34