C# 异常:从DocumentDB查询时发生Microsoft.Azure.Documents.RequestRateTooLargeException

C# 异常:从DocumentDB查询时发生Microsoft.Azure.Documents.RequestRateTooLargeException,c#,bulkinsert,azure-cosmosdb,resque-retry,C#,Bulkinsert,Azure Cosmosdb,Resque Retry,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.Eq

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;
            }
        }
    }
}
this.ProcessRequestSync(()=>this.Client.CreateDocumentQuery(this.DocumentDBCollectionLink)。其中(d=>d.name.Equals(name)和&d.code.Equals(code)和&d.Type.Equals(this.documentType)和&d.CreatedBy.Equals(myName.ToList());
公共动态ProcessRequestSync(Func getRequest)
{
var延迟=时间跨度为零;
var minDelayTime=新的时间跨度(0,0,1);
对于(;;)
{
尝试
{
睡眠(延迟);
返回getRequest();
}
捕获(DocumentClientException DocumentClientException)
{
var statusCode=(int)documentClientException.statusCode;
如果(状态代码==429 | |状态代码==503)
{
string errorMessage=string.Format(“在具有{0}状态和{1}重试时间的DocumentDB处失败”,状态代码,documentClientException.RetryAfter);
this.Logger.Log(错误消息);
//如果请求速率过大或服务暂时不可用,请退出
延迟=时间跨度。比较(documentClientException.RetryAfter,minDelayTime)>=0?documentClientException.RetryAfter:minDelayTime;
}
其他的
{
投掷;
}
}
}
}
这是requestRateTooLarge异常引发时重试逻辑的方法

我不确定它是否工作正常

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

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

您还需要AggregateException的catch块,并检查AggregateException.InnerException是否为DocumentClientException,并对StatusCode==429执行相同的检查。由于查询执行是异步的,因此您可能无法获取正在清除包装在AggregateException中的节流异常


如果你能发布一份完整的报告,我们也许能够确定问题所在。

基于@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;
                }
            }
        }
    }

这里还值得注意的是,在处理节流异常时,不要等待Timespan.Zero。而是查看返回的响应,该响应将包含retry after值。等待该时间段。这是错误的代码。
catch(AggregateException AggregateException)
如果
聚合异常。InnerException
不是
DocumentClientException
,则吞咽异常,这可能导致(!QueryOne)时出现
无休止地循环。@core虽然理论上你是正确的,但实际上我已经在生产中使用了这段代码将近一年了,工作中设置了一个终止时间-它从来没有达到这个终止时间,因此这意味着你的循环场景在实践中不可能发生。不管怎样,你提出微妙的建议可能对其他人有用修复/编辑答案,然后声明完整答案为“错误代码”!你真的应该在异步代码中使用
Thread.Sleep