rabbitmq 发件箱MassTransit中的DbUpdateConcurrencyException

798qvoo8  于 2023-10-20  发布在  RabbitMQ
关注(0)|答案(1)|浏览(203)

我们目前正在使用MassTransit和MassTransit嵌入式发件箱,在我们的开发和测试环境中取得了普遍成功的结果。然而,当我们过渡到现场环境时,我们遇到了一些不寻常的行为。具体来说,随着消息量的增加,我们开始在实时环境中收到大量的Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException错误。
MassTransit.EntityFrameworkCore:8.0.16
Microsoft. MicrosoftFrameworkCore.SqlServer:7.0.8,
net7.0

MT-Fault-Message:   The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
MT-Fault-StackTrace:    at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyExceptionAsync(RelationalDataReader reader, Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetAsync(Int32 startCommandIndex, RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Update.Internal.SqlServerModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at MassTransit.EntityFrameworkCoreIntegration.EntityFrameworkOutboxContextFactory`1.<>c__DisplayClass6_0`1.<<Send>g__Execute|0>d.MoveNext() in /_/src/Persistence/MassTransit.EntityFrameworkCoreIntegration/EntityFrameworkCoreIntegration/EntityFrameworkOutboxContextFactory.cs:line 76
--- End of stack trace from previous location ---
at MassTransit.EntityFrameworkCoreIntegration.EntityFrameworkOutboxContextFactory`1.<>c__DisplayClass6_0`1.<<Send>g__Execute|0>d.MoveNext() in /_/src/Persistence/MassTransit.EntityFrameworkCoreIntegration/EntityFrameworkCoreIntegration/EntityFrameworkOutboxContextFactory.cs:line 104
--- End of stack trace from previous location ---
at MassTransit.EntityFrameworkCoreIntegration.EntityFrameworkOutboxContextFactory`1.<>c__DisplayClass6_0`1.<<Send>g__Execute|0>d.MoveNext() in /_/src/Persistence/MassTransit.EntityFrameworkCoreIntegration/EntityFrameworkCoreIntegration/EntityFrameworkOutboxContextFactory.cs:line 104
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass30_0`2.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at MassTransit.EntityFrameworkCoreIntegration.EntityFrameworkOutboxContextFactory`1.Send[T](ConsumeContext`1 context, OutboxConsumeOptions options, IPipe`1 next) in /_/src/Persistence/MassTransit.EntityFrameworkCoreIntegration/EntityFrameworkCoreIntegration/EntityFrameworkOutboxContextFactory.cs:line 113
at MassTransit.Middleware.OutboxConsumeFilter`2.Send(ConsumeContext`1 context, IPipe`1 next) in /_/src/MassTransit/Middleware/OutboxConsumeFilter.cs:line 41
at MassTransit.Middleware.OutboxConsumeFilter`2.Send(ConsumeContext`1 context, IPipe`1 next) in /_/src/MassTransit/Middleware/OutboxConsumeFilter.cs:line 41
at MassTransit.Middleware.RetryFilter`1.Attempt(TContext context, RetryContext`1 retryContext, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 158
at MassTransit.Middleware.RetryFilter`1.Attempt(TContext context, RetryContext`1 retryContext, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 238
at MassTransit.Middleware.RetryFilter`1.MassTransit.IFilter<TContext>.Send(TContext context, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 128
at MassTransit.Middleware.RetryFilter`1.MassTransit.IFilter<TContext>.Send(TContext context, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 47
at MassTransit.Middleware.RetryFilter`1.MassTransit.IFilter<TContext>.Send(TContext context, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 118
at MassTransit.Middleware.RetryFilter`1.MassTransit.IFilter<TContext>.Send(TContext context, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 47
at MassTransit.Middleware.RetryFilter`1.MassTransit.IFilter<TContext>.Send(TContext context, IPipe`1 next) in /_/src/MassTransit/Middleware/RetryFilter.cs:line 118

为了解决这个问题,我尝试通过配置我们的消息重试机制来处理异常,如下所示:

endpointConfigurator.UseMessageRetry(r =>
{
    r.Handle<DbUpdateConcurrencyException>();
    r.None();
});

endpointConfigurator.UseMessageRetry(r =>
{
    r.Ignore<DbUpdateConcurrencyException>();
    r.Intervals(
        TimeSpan.FromMilliseconds(10),
        TimeSpan.FromMilliseconds(100),
        TimeSpan.FromSeconds(1)
    );
});

不幸的是,即使使用这种设置,仍有DbUpdateConcurrencyException错误最终出现在错误队列中的情况。特别令人困惑的是,当这些异常发生在其他没有显式配置为忽略它们的队列中时,它们也会影响应该忽略它们的队列。
此外,我试图通过将DbContext的服务生命周期设置为Transient来解决这个问题,但是这个更改没有产生预期的结果。
我们目前正在寻求帮助和建议,以解决这个问题,并确保我们的应用程序在现场环境中的可靠运行。

b1uwtaje

b1uwtaje1#

你应该总是重试DbUpdateConcurrencyException,然而,你会竭尽全力确保你不 * 重试它们。您的重试配置错误。

endpointConfigurator.UseMessageRetry(r =>
{
    r.Handle<DbUpdateConcurrencyException>();
    r.Intervals(
        TimeSpan.FromMilliseconds(10),
        TimeSpan.FromMilliseconds(100),
        TimeSpan.FromSeconds(1)
    );
});

相关问题