RetryAfter TimeSpan如何计算?

时间:2018-02-15 16:53:00

标签: azure-cosmosdb

我有一个功能,它是订阅主​​题的服务总线触发器,它聚合特定实体(1:M)的数据,并最终调用DocumentDb存储过程来实现实体。因此,对于每条消息,请说出我正在操作的60个实体(upserting)。

我是垃圾邮件(我猜)CosmosDb(RU是400,所以不是很大,它只是一个测试Db)并开始接收Request rate is too large例外,所以我研究了如何最好地处理它,并注意到某个地方的代码示例利用了RetryAfter上的DocumentClientException属性,并想知道如何计算此属性?

docs并不完全正确,但就生产级别事件而言,我希望能够提供这类信息。

每次尝试都是某种斐波那契序列还是?此外,它如何跟踪已经进行了多少次尝试? (或者是吗?)

1 个答案:

答案 0 :(得分:0)

时间跨度背后的逻辑解释为here

使用绑定获取DocumentClient时,它使用default constructor

客户端已defaultRequest rate is too large个错误重试一次(默认为9次)。

如果您想要更精细或自定义控制,您可以自行管理DocumentClient实例而无需绑定,并设置MaxRetryAttemptsOnThrottledRequestsMaxRetryWaitTimeInSeconds

如果要创建自己的DocumentClient,我建议将其设为static

无论哪种方式,如果您尝试/抓住DocumentClientException并检查StatusCode 429,您将能够捕捉超出MaxRetryAttemptsOnThrottledRequests的方案。

例如:

#r "Microsoft.Azure.Documents.Client"
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.Net;
using System.Configuration;

private static string endpointUrl = ConfigurationManager.AppSettings["cosmosDBAccountEndpoint"]; 
private static string authorizationKey = ConfigurationManager.AppSettings["cosmosDBAccountKey"]; 
private static DocumentClient client = new DocumentClient(new Uri(endpointUrl), authorizationKey, new ConnectionPolicy() {
            RetryOptions = new RetryOptions()
            {
                MaxRetryAttemptsOnThrottledRequests = 10,
                MaxRetryWaitTimeInSeconds  = 20
            }
        });
});

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    string id = req.GetQueryNameValuePairs()
        .FirstOrDefault(q => string.Compare(q.Key, "id", true) == 0)
        .Value;
    if (string.IsNullOrEmpty(id)){
          return req.CreateResponse(HttpStatusCode.BadRequest);
    }

    Uri documentUri = UriFactory.CreateDocumentUri("name of database","name of collection",id);
    try {
        Document doc = await client.ReadDocumentAsync(documentUri);
    }
    catch(DocumentClientException ex){
        int statusCode = (int)ex.StatusCode;
        if (statusCode == 429) {
            // Request rate errors went over the MaxRetryAttemptsOnThrottledRequests
            // Do something you want here
        }

        throw;
    }
    if (doc == null){
      return req.CreateResponse(HttpStatusCode.NotFound);
    }

    return req.CreateResponse(HttpStatusCode.OK, doc);
}