【问题标题】:Exception: Microsoft.Azure.Documents.RequestRateTooLargeException while querying from DocumentDB异常:从 DocumentDB 查询时出现 Microsoft.Azure.Documents.RequestRateTooLargeException
【发布时间】:2015-05-30 06:59:48
【问题描述】:

y 查询类似于

this.ProcessRequestSync(() => this.Client.CreateDocumentQuery<Model>(this.DocumentDBCollectionLink).Where(d => d.name.Equals(name) && d.code.Equals(code) && d.Type.Equals(this.documentType) && d.CreatedBy.Equals(myName).ToList<Model>());

 public dynamic ProcessRequestSync(Func<dynamic> getRequest)
{
    var delay = TimeSpan.Zero;
    var minDelayTime = new TimeSpan(0, 0, 1);
    for (;;)
    {
        try
        {
            Thread.Sleep(delay);
            return getRequest();
        }
        catch (DocumentClientException documentClientException)
        {
            var statusCode = (int)documentClientException.StatusCode;
            if (statusCode == 429 || statusCode == 503)
            {
                string errorMessage = string.Format("failed at DocumentDB with {0} status and {1} retry time", statusCode, documentClientException.RetryAfter);
                this.Logger.Log(errorMessage );

                // Back off if the request rate is too large or the service is temporarily unavailable
                delay = TimeSpan.Compare(documentClientException.RetryAfter, minDelayTime) >= 0 ? documentClientException.RetryAfter: minDelayTime;
            }
            else
            {
                throw;
            }
        }
    }
}

这是requestRateTooLarge异常引发时重试逻辑的方法。

我不确定,它是否工作正常,

我在一次查询和插入大约 4000 条记录时遇到异常:Microsoft.Azure.Documents.RequestRateTooLargeException,

我使用相同的重试逻辑进行插入,它工作正常。 我没有收到任何错误,也成功插入了所有记录,但无法获取查询数据。

【问题讨论】:

    标签: c# bulkinsert azure-cosmosdb resque-retry


    【解决方案1】:

    根据上面/下面的@aravind Ramachandra 和@Ryan CrawCour 的回答,这就是我用来解决问题的方法。

        public async Task SaveToDocDb(dynamic jsonDocToSave)
        {
    
            using (var client = new DocumentClient(endpoint, authKey))
            {
                var queryDone = false;
                while (!queryDone)
                {
                    try
                    {
                        await client.CreateDocumentAsync(docCollectionlink, jsonDocToSave);
                        queryDone = true; 
                    }
                    catch (DocumentClientException documentClientException)
                    {
                        var statusCode = (int)documentClientException.StatusCode;
                        if (statusCode == 429 || statusCode == 503)   
                            Thread.Sleep(documentClientException.RetryAfter);
                        else
                            throw;
                    }
                    catch (AggregateException aggregateException)
                    {
                        if(aggregateException.InnerException.GetType() == typeof(DocumentClientException)){
    
                            var docExcep = aggregateException.InnerException as DocumentClientException;
                            var statusCode = (int)docExcep.StatusCode;
                            if (statusCode == 429 || statusCode == 503)
                                Thread.Sleep(docExcep.RetryAfter);
                            else
                                throw;
                        }
                         else 
                           throw;
                    }
                }
            }
        }
    

    【讨论】:

    • 这是错误的代码。如果aggregateException.InnerException 不是DocumentClientExceptioncatch (AggregateException aggregateException) 会吞下异常,这可能会导致while(!queryDone) 无限循环。
    • @core 虽然理论上你是正确的,但在实践中,我已经在生产中使用了近一年的这段代码,并且在工作中设置了终止时间 - 它从未达到这个终止时间,因此意味着您的循环场景在实践中不会发生。无论如何,建议您进行细微的修复/编辑答案而不是声明完整的答案“错误代码”可能对其他人有用!
    • 你真的应该在异步代码中使用Thread.Sleep吗? Task.Delay不是你想要的吗?
    【解决方案2】:

    您还需要一个用于 AggregateException 的 catch 块,并检查 AggregateException.InnerException 是否为 DocumentClientException 并对 StatusCode == 429 执行相同的检查。由于查询执行是异步的,因此您可能会将节流异常包装在一个聚合异常。

    如果您可以发布完整的重现,我们也许能够明确地确定问题。

    【讨论】:

    • 这里还值得注意的是,在处理节流异常时不要等待 Timespan.Zero。而是查看您返回的响应,该响应将具有 retry-after 值。等待那个时间段。
    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 2017-08-06
    相关资源
    最近更新 更多