我们目前正在使用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来解决这个问题,但是这个更改没有产生预期的结果。
我们目前正在寻求帮助和建议,以解决这个问题,并确保我们的应用程序在现场环境中的可靠运行。
1条答案
按热度按时间b1uwtaje1#
你应该总是重试
DbUpdateConcurrencyException
,然而,你会竭尽全力确保你不 * 重试它们。您的重试配置错误。