在 cosmosdb 中创建文档时取消

Posted

技术标签:

【中文标题】在 cosmosdb 中创建文档时取消【英文标题】:canceled while creating documents in cosmosdb 【发布时间】:2019-07-14 12:19:04 【问题描述】:

我们正在使用 cosmosdb 来记录我们的应用程序日志。我们的日志有两层,一层有一般信息,另一层有一般日志的更详细信息。我们还将这些副本记录在其他两个集合中以进行备份。所以我们有完整的四个集合。在我们的代码中,我们使用 Async CreateDocumentAsync 来创建这些日志。我们将任务存储在一个列表中,并使用 Task.WaitAll 来完成所有任务。在开发环境中,我们没有看到任何错误,但在生产环境中,我们在创建新文档时在应用程序洞察中看到取消的错误。下面的示例图片。

下面是我们使用的代码结构

API 控制器代码

public void Log(LogModel logObject)

    try
    
        _context.Save(logObject);
    
    catch(Exception ex)
    
        _azureTelemtry.TrackTrace($"Exception occured: ex.ToString()");
    

上下文保存方法

public void Save(LogModel logObject)

    List<Task> saveTasks = new List<Task>();
    LogInfo logInfo = logObject.logInfo;
    LogDetails logDetails = logObject.logDetails;
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, primaryLogInfoCollectionID), logInfo));
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, archieveLogInfoCollectionID), logInfo));    
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, primaryLogDetailsCollectionID), logDetails));
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, archieveLogDetailsCollectionID), logDetails));
    Task.WaitAll(saveTasks.ToArrays());

异常详情

System.AggregateException:在 MyApplication.Logging.Controllers.ApiController.Log (MyApplication.Logging,版本=2.0.0.0,文化=中性, PublicKeyToken=nullMyApplication.Logging,版本=2.0.0.0, 文化=中立,PublicKeyToken=null: C:\TFS\CA\Logging\Release\Release 3.0-Hotfix\Logging\Controllers\ApiController.csMyApplication.Logging,版本=2.0.0.0,Culture=neutral,PublicKeyToken=null: 57) 在 lambda_method(匿名托管的 DynamicMethods 程序集, 版本=0.0.0.0,文化=中性,PublicKeyToken=null) 在 Microsoft.Extensions.Internal.ObjectMethodExecutor+c__DisplayClass33_0.b__0 (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__12.MoveNext (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__10.MoveNext (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__14.MoveNext (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+d__22.MoveNext (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+d__17.MoveNext (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+d__15.MoveNext (Microsoft.AspNetCore.Mvc.Core,版本=2.0.2.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Builder.RouterMiddleware+d__4.MoveNext (Microsoft.AspNetCore.Routing,版本=2.0.1.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware+d__11.MoveNext (Microsoft.AspNetCore.Server.IISIntegration,版本=2.0.1.0, 文化=中性,PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware+d__3.MoveNext (Microsoft.AspNetCore.Hosting,版本=2.0.1.0,文化=中性, PublicKeyToken=adb9793829ddae60) 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1+d__2.MoveNext (Microsoft.AspNetCore.Server.Kestrel.Core,版本=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60) 内部异常 System.Threading.Tasks.TaskCanceledException 处理于 MyApplication.Logging.Controllers.ApiController.Log:

【问题讨论】:

【参考方案1】:

您不等待任务。此外Save 函数是同步的,因此Task.WaitAll(saveTasks.ToArrays()); runs synchronpusly

至少我希望public void Save(LogModel logObject)public Task Save(LogModel logObject)Task.WaitAll(saveTasks.ToArrays());return Task.WhenAll(saveTasks.ToArrays());

public Task Save(LogModel logObject)

    List<Task> saveTasks = new List<Task>();
    LogInfo logInfo = logObject.logInfo;
    LogDetails logDetails = logObject.logDetails;
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, primaryLogInfoCollectionID), logInfo));
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, archieveLogInfoCollectionID), logInfo));    
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, primaryLogDetailsCollectionID), logDetails));
    saveTasks.Add(documentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, archieveLogDetailsCollectionID), logDetails));

    return Task.WhenAll(saveTasks.ToArrays());

如果您的意图是触发任务并忘记,现在您可以使用_context.Save(logObject);,否则您需要使用Task

另一个问题是:上面的代码打开了 4 个任务,并且无法控制地处理它。 .Net Core 中默认的 Concurrent Execution Limit 是 10。现在想想Save 方法连续调用了 3 次,还没有完成。这意味着您需要有 12 个并发任务。但是 .Net Core 有 10 个限制。我相信最后两个任务会被取消。

【讨论】:

以上是关于在 cosmosdb 中创建文档时取消的主要内容,如果未能解决你的问题,请参考以下文章

从CosmosDB中读取集合中所有分区的文档

当我尝试使用 python 创建一个空白文档时,Google API 没有在驱动器中创建任何文档

Spring Boot:如果不存在,则在启动时在 mongodb 中创建文档

如何在使用模板的 word 文档中创建下拉列表?

如何在 C# 中创建相对于用户文档的文件目录?

在 C# 中创建 Word 文档