【问题标题】:MongoDB async IIdGenerator for InsertOneAsync operation用于 InsertOneAsync 操作的 MongoDB 异步 IIdGenerator
【发布时间】:2021-06-30 16:59:11
【问题描述】:

我们已经公开了一个 JobService(它是使用 kestrel 的 Dotnet Core 服务),它为我们的对象(JobDocument)进行 MongoDB 更新,并且看到在对 createJob 的 Post 调用的情况下,它实际上触发了 MongoDB.Driver.MongoCollectionBase`1.InsertOneAsync有一个性能冲击,即。大约 200 个并发请求使服务无响应。经过调试和使用一些工具,发现问题出在api调用InsertOneAsync。这是使用我们对 GenerateId 的自定义实现,它使用同步函数调用 FindOneAndUpdate。GenerateId 是否有异步方式。如何做到这一点?参考使用指向相同的工具 Ben Blocking 检测器附加堆栈:

{"Timestamp":"2021-04-03T15:22:38.5854816+05:30","Level":"Warning","MessageTemplate":"Blocking method has been invoked and blocked, this can lead to threadpool starvation.\r\n{stackTrace}","Properties":{"stackTrace":"   

at System.Threading.Tasks.TplEventSource.TaskWaitBegin(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, Int32 TaskID, TaskWaitBehavior Behavior, Int32 ContinueWithTaskID)\r\n   
at System.Threading.Tasks.Task.InternalWaitCore(Int32 millisecondsTimeout, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Connections.TcpStreamFactory.CreateStream(EndPoint endPoint, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelper(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Connections.BinaryConnection.Open(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.ConnectionPools.ExclusiveConnectionPool.PooledConnection.Open(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.ConnectionPools.ExclusiveConnectionPool.AcquiredConnection.Open(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Servers.Server.GetChannel(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Bindings.ServerChannelSource.GetChannel(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Bindings.ChannelSourceHandle.GetChannel(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Operations.RetryableWriteContext.Initialize(CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Operations.RetryableWriteContext.Create(IWriteBinding binding, Boolean retryRequested, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Operations.RetryableWriteOperationExecutor.Execute[TResult](IRetryableWriteOperation`1 operation, IWriteBinding binding, Boolean retryRequested, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.Core.Operations.FindAndModifyOperationBase`1.Execute(IWriteBinding binding, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.OperationExecutor.ExecuteWriteOperation[TResult](IWriteBinding binding, IWriteOperation`1 operation, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.ExecuteWriteOperation[TResult](IClientSessionHandle session, IWriteOperation`1 operation, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.FindOneAndUpdate[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, UpdateDefinition`1 update, FindOneAndUpdateOptions`2 options, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass53_0`1.<FindOneAndUpdate>b__0(IClientSessionHandle session)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.FindOneAndUpdate[TProjection](FilterDefinition`1 filter, UpdateDefinition`1 update, FindOneAndUpdateOptions`2 options, CancellationToken cancellationToken)\r\n   
at JobManager.Data.MongoDB.IdGenerator.JobIdGenerator.GenerateId(Object container, Object document)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.AssignId(TDocument document)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.ConvertWriteModelToWriteRequest(WriteModel`1 model, Int32 index)\r\n   
at System.Linq.Enumerable.SelectIterator[TSource,TResult](IEnumerable`1 source, Func`3 selector)+MoveNext()\r\n   
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n   
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation..ctor(CollectionNamespace collectionNamespace, IEnumerable`1 requests, MessageEncoderSettings messageEncoderSettings)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.CreateBulkWriteOperation(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.BulkWriteAsync(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.BulkWriteAsync(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass25_0.<BulkWriteAsync>b__0(IClientSessionHandle session)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionImpl`1.BulkWriteAsync(IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)\r\n   
at MongoDB.Driver.MongoCollectionBase`1.<>c__DisplayClass68_0.<InsertOneAsync>b__0(IEnumerable`1 requests, BulkWriteOptions bulkWriteOptions)\r\n   
at MongoDB.Driver.MongoCollectionBase`1.InsertOneAsync(TDocument document, InsertOneOptions options, Func`3 bulkWriteAsync)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at MongoDB.Driver.MongoCollectionBase`1.InsertOneAsync(TDocument document, InsertOneOptions options, Func`3 bulkWriteAsync)\r\n   
at MongoDB.Driver.MongoCollectionBase`1.InsertOneAsync(TDocument document, InsertOneOptions options, CancellationToken cancellationToken)\r\n   
at Code.DataProtection.JobManager.Data.MongoDB.Repositories.MongoJobRepository.Code.DataProtection.JobManager.Data.Contract.IJobRepository.CreateJob(Job job)\r\n 
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Code.DataProtection.JobManager.Data.MongoDB.Repositories.MongoJobRepository.Code.DataProtection.JobManager.Data.Contract.IJobRepository.CreateJob(Job job)\r\n   
at Code.DataProtection.JobManager.Services.JobService.CreateJob(Job job)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Code.DataProtection.JobManager.Services.JobService.CreateJob(Job job)\r\n   
at Code.DataProtection.JobManager.Services.JobService.Code.DataProtection.JobManager.Contract.Interfaces.IJobService.CreateJobWithWorkflow(Job job)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Code.DataProtection.JobManager.Services.JobService.Code.DataProtection.JobManager.Contract.Interfaces.IJobService.CreateJobWithWorkflow(Job job)\r\n   
at Code.DataProtection.JobManager.Api.Controllers.v2.JobsController.CreateJob(Job job)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Code.DataProtection.JobManager.Api.Controllers.v2.JobsController.CreateJob(Job job)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAwaitedAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAwaitedAsync()\r\n   
at Code.DataProtection.Common.Utils.Filters.ContextFilter.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Code.DataProtection.Common.Utils.Filters.ContextFilter.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAwaitedAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Controller.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n   
at Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n  
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResourceFilter()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Routing.ActionEndpointFactory.<>c__DisplayClass7_0.<CreateRequestDelegate>b__0(HttpContext context)\r\n   
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)\r\n   
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)\r\n   
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)\r\n   
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)\r\n   
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_1.<UseMiddleware>b__2(HttpContext context)\r\n   
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)\r\n   
at CorrelationId.CorrelationIdMiddleware.Invoke(HttpContext context, ICorrelationContextFactory correlationContextFactory)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at CorrelationId.CorrelationIdMiddleware.Invoke(HttpContext context, ICorrelationContextFactory correlationContextFactory)\r\n   
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_1.<UseMiddleware>b__2(HttpContext context)\r\n   
at Code.DataProtection.Common.Utils.ExceptionHandler.ExceptionHandlerMiddleware.Invoke(HttpContext context)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Code.DataProtection.Common.Utils.ExceptionHandler.ExceptionHandlerMiddleware.Invoke(HttpContext context)\r\n   
at Ben.Diagnostics.BlockingDetectionMiddleware.Invoke(HttpContext httpContext)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Ben.Diagnostics.BlockingDetectionMiddleware.Invoke(HttpContext httpContext)\r\n   
at Microsoft.AspNetCore.Mvc.Versioning.ApiVersioningMiddleware.InvokeAsync(HttpContext context)\r\n   
at Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware.Invoke(HttpContext context)\r\n   
at Microsoft.AspNetCore.Hosting.HostingApplication.ProcessRequestAsync(Context context)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.ProcessRequestsAsync[TContext](IHttpApplication`1 httpApplication)\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.ProcessRequestsAsync[TContext](IHttpApplication`1 httpApplication)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnectionMiddleware`1.OnConnectionAsync(ConnectionContext connectionContext)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.KestrelConnection.ExecuteAsync()\r\n   
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.KestrelConnection.ExecuteAsync()\r\n   
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.KestrelConnection.System.Threading.IThreadPoolWorkItem.Execute()\r\n   
at System.Threading.ThreadPoolWorkQueue.Dispatch()\r\n   
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()\r\n","EventId":{"Id":6,"Name":"BlockingMethodCalled"},"SourceContext":"Ben.Diagnostics.BlockingMonitor","ActionId":"25c60a2a-f366-415b-8f16-66e10f134608","ActionName":"Code.DataProtection.JobManager.Api.Controllers.v2.JobsController.CreateJob (JobManager.Api)","RequestId":"0HM7MGOIK401C:00000001","RequestPath":"/api/jobmanager/v2.0/jobs","SpanId":"|11136163-4c80e7d34af376d0.","TraceId":"11136163-4c80e7d34af376d0","ParentId":"","ConnectionId":"0HM7MGOIK401C"}}

【问题讨论】:

  • 您的自定义 id 生成代码是否使用 FindOneAndUpdate 进行顺序 id 生成以增加数据库中的计数器文档?如果没有,将有助于查看该代码。
  • 是的,我们正在使用 FindOneAndUpdate 来增加计数器。我们不能使用 FindOneAndUpdateAsync,因为它要求 GenerateId api 也是异步的,但它不受支持。
  • public class JobIdGenerator : IIdGenerator{ public object GenerateId(object container, object doc) { IMongoCollection&lt;SequenceDocument&gt; idSeqColl = (IMongoCollection&lt;JobDocument&gt;)container).Database.GetCollection&lt;SequenceDocument&gt;("Sequence"); var filter = Builders&lt;SequenceDocument&gt;.Filter.Empty; var update = Builders&lt;SequenceDocument&gt;.Update.Inc(a =&gt; a.Value, 1); return idSeqColl.FindOneAndUpdate(filter, update, new FindOneAndUpdateOptions&lt;SequenceDocument, SequenceDocument&gt; {ReturnDocument = ReturnDocument.After, IsUpsert = true}).Value;

标签: c# mongodb .net-core mongodb-.net-driver kestrel


【解决方案1】:

我相信您的性能问题源于使用 mongodb 服务器生成增量 ID 的技术,而不是因为无法使用 async/await

这是众所周知的顺序 id 生成的缩放/性能限制,因为 mongodb 必须锁定计数器文档才能增加值。

例如:假设单个 FindOneAndUpdate 操作需要 50 毫秒来更新计数器。现在同时从 200 个线程执行此操作大约需要 200 x 50ms = 10 秒或更多。即在任何给定时间只允许 1 个线程/操作写入计数器文档,并且每个操作/线程获得一个排他锁。

你有几个选择:

  • 放弃使用增量 ID 并改用 ObjectId
  • 创建一个后台服务,在当前库存不足的情况下预先生成成批的顺序 ID。那么您的 JobIdGenerator 将“FindOneAndUpdate”下一个未使用的 ID 为 IsUsed:true,而不是尝试增加单个计数器文档。

另外,由于没有 IIdGenerator.GenerateIdAsync 方法,您可能希望自己掌握并从您的存储库/其他设置值,而不是在保存/创建新实体时使用 IIdGenerator

【讨论】:

  • 想了解为什么 200 个并发请求会使服务无响应,从而导致其他 api 调用无响应?是因为线程池饥饿和 Kestrel 处理线程池的方式。或者有没有办法让 Kestrel 为每个端点配置线程池,以便其他非 mongo db 端点继续工作并且不响应?
  • @nikhilambastha mongodb 驱动程序在后台进行虚假同步(异步同步反模式)以保持向后兼容性。 FindOneAndUpdate 是锁定线程超过所需时间的罪魁祸首。您的服务中可能还有其他地方也使用了导致问题的传统同步异步 API。您必须从上到下一直异步/等待以进行 io 绑定工作。所以不要使用 IIdGenerator.GenerateId 并创建自己的方法/服务,以异步方式吐出增量 Id。从该服务中获取下一个增量 id 并设置在实体上。
  • Endpoint (url/create)-queries/update mongodb 正在使用 FindOneAndUpdate 并且正在阻塞。因此,当我对该 API 进行多次调用时,该端点的下一个 api 变得无响应。在此处理时间期间,假设我在同一服务中调用另一个端点说端点(/ping),它只返回真/假,它也变得无响应。为什么会这样?是因为 Kestrel 在内部使用线程池的方式吗?我们是否通过任何配置更改使其对差异端点使用单独的线程池,这样即使我的创建 api 没有响应,我的 ping 响应也很好。
  • 请阅读this article。它将帮助您了解由于阻塞代码导致的线程池饥饿。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 2020-10-25
相关资源
最近更新 更多