【问题标题】:Cosmos DB call never returns with async callCosmos DB 调用永远不会通过异步调用返回
【发布时间】:2019-10-29 17:48:59
【问题描述】:

我在 WebApi 中有一个方法,该方法通过返回进程配置文件但永远不会返回的 SQL API 调用 Cosmos。任务挂起并且永远不会完成。我可以在 Debug 的 Threads 窗口中看到该任务。对同一数据库容器的其他调用运行良好。几次通话后,我必须重新启动 IIS 以清除任务。不抛出异常。我已经在有和没有尝试捕获的情况下运行它。复制到另一个控制台应用程序项目中的相同方法可以正常工作。是否存在已知的 cosmos 超时导致结果过大的问题?这应该只返回 2 个项目。实时 Cosmos DB 和本地运行的 Cosmos 模拟器的行为相同。

我正在使用最新的 Cosmos 包。

<package id="Microsoft.Azure.Cosmos" version="3.3.2" targetFramework="net472" />

构造函数

client = new CosmosClient(url, primaryKey, new CosmosClientOptions()
{
    RequestTimeout = new TimeSpan(0, 0, 20),
    ApplicationRegion = "West US 2",
    ConnectionMode = ConnectionMode.Gateway,
    GatewayModeMaxConnectionLimit = 1000,
    MaxRetryAttemptsOnRateLimitedRequests = 1000,
});

database = client.GetDatabase("MyDatabase");
container = configDatabase.GetContainer("Configs");

此方法永远不会从等待项中返回。ReadNextAsync()

public async Task<Dictionary<int, string>> GetConfigurationList()
{
   var values = new Dictionary<int, string>();
   var query = new QueryDefinition("SELECT c.ConfigId, c.ConfigDescription FROM c where c.DataSourceType='CSV'");

   var items = container.GetItemQueryIterator<(int ConfigId, string ConfigDescription )>(query);

   while (items.HasMoreResults)
   {
       FeedResponse<(int ConfigId, string ConfigDescription )> configs = await items.ReadNextAsync();

       foreach (var item in configs)
       {
            values.Add(item.ConfigId, item.ConfigDescription);
        }
    }
    return values;
}

这个方法每次都很好用

public async Task<LetterConfiguration> GetConfiguration(int id)
{
  var query = new QueryDefinition("SELECT * FROM c where c.ConfigId= @id").WithParameter("@id",id);

  var configItems = container.GetItemQueryIterator<ConfigFile>(query);

  while (configItems.HasMoreResults)
  {
     FeedResponse<ConfigFile> configs = await configItems.ReadNextAsync();
     if(configs.Count == 1)
     {
        return configs.FirstOrDefault();
     }
  }
  return null;
}

【问题讨论】:

  • 如果在方法 GetConfigurationList 中使用类型化对象,即 ConfigFile 而不是 Tuple,会发生什么情况。还有一些其他问题 - 您正在开发的应用程序是什么?在链中的任何地方,您的代码是否破坏了异步/等待模式?建议使用 ConfigureAwait(false) 进行异步调用。
  • 使用类型化的对象做同样的事情。我试图 Tuple 看看这是否是数据量问题。 async/await 用于从控制器到它所在的存储库。该应用程序用于生成套用信函。 ConfigFiles 定义了如何在不同的表单上填充数据。我尝试了 ConfigureAwait(false),它仍然没有返回。
  • 如果在 Web API 方法的末尾(最后一行)添加断点,它会被命中吗?如果是这样,您可能会在某处丢失一些 await 并丢失异步上下文
  • 断点永远不会被命中,调用者(swagger UI、邮递员)的请求永远不会完成。
  • @kekindt - 当您直接在 Comos DB 查询刀片(在 Azure 门户中)运行此查询时,查询会产生任何结果吗?

标签: c# azure azure-cosmosdb


【解决方案1】:

这最终导致调用存储库方法的控制器中缺少等待。感谢大家的意见。

【讨论】:

    【解决方案2】:

    几条建议:

    1. 在调用 ReadNextAsync 时是否检查是否有异常?使用 Try...Catch

    2. 为 GetItemQueryIterator 和 FeedResponse 使用类型化对象

    更新:试试这个来查询选择性字段 -

                var query = new QueryDefinition("SELECT c.ConfigId, c.ConfigDescription FROM c where c.DataSourceType='CSV'");
    
                var items = container.GetItemQueryStreamIterator(query);
    
    
                while (items.HasMoreResults)
                {
                    using (ResponseMessage response = await items.ReadNextAsync())
                    {
                        using (StreamReader sReader = new StreamReader(response.Content))
                        using (JsonTextReader jsonReader = new JsonTextReader(sReader))
                        {
                            JsonSerializer jsonSerializer = new JsonSerializer();
                            dynamic values = jsonSerializer.Deserialize<dynamic>(jsonReader).Documents;
                            Console.WriteLine($"Name: {values[0].ConfigId}");
                        }
                    }
                }
    

    【讨论】:

    • 1.使用 try catch 时不会抛出异常。 2. 使用类型化对象做同样的事情。我尝试了 Tuple 看看是否是数据量问题。
    • letterContainers 对象是否设置正确?
    • 是的。我在审查后重命名了一些变量,还没有再次编译它。我已经在示例中修复了它。对不起。
    • 您是否尝试过一个简单的查询(以防万一排除这里的任何犯规)-“SELECT * FROM c”?抱歉想不出任何明显的原因。它看起来确实不错,而且 Cosmos DB 没有性能问题。
    猜你喜欢
    • 1970-01-01
    • 2016-01-16
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多