如何在Microsoft.Azure.Cosmos SDK中控制超时、重试及重试间隔?
配置Microsoft.Azure.Cosmos客户端实现总耗时限制(含重试)
我正在使用推荐的SDK——Microsoft.Azure.Cosmos,希望限制Cosmos创建文档的总耗时:最坏情况下(所有重试均超时),超时、重试间隔及重试操作的总时长必须控制在5秒内。我已经在Service Bus SDK及其他API中通过Polly实现了这个需求,能轻松控制相关参数。
这么做的原因是我的服务调用方会在设定时间后超时并取消请求,我希望配置应用确保多数情况下能在请求被取消前完成所有重试。虽然可以传递取消令牌,但不如在指定时间窗口内完成所有操作整洁。
目前发现Cosmos SDK的多数重试选项仅针对限流场景,同时我注意到部分请求会通过HTTP发送,部分会在直接模式下通过TCP发送。
以下是我在.NET 8项目Program.cs中创建Cosmos客户端的现有代码:
CosmosClient cosmosClient = new( connectionString: "<connection-string-goes-here>", new CosmosClientOptions { ApplicationPreferredRegions = new List<string> { Regions.SoutheastAsia } // 我期望这里能有控制超时和重试的配置项 } );
实现方案
1. 利用CosmosClientOptions内置配置控制
可以通过CosmosClientOptions的多个参数组合,实现对总耗时的控制:
- RequestTimeout:设置单次请求的超时时间,是TCP/HTTP模式下的基础超时阈值
- RetryOptions:调整重试次数、间隔,甚至自定义重试逻辑,覆盖仅针对限流的默认策略
示例配置代码:
CosmosClient cosmosClient = new( connectionString: "<connection-string-goes-here>", new CosmosClientOptions { ApplicationPreferredRegions = new List<string> { Regions.SoutheastAsia }, // 单次请求超时设为1秒,结合重试次数控制总时长 RequestTimeout = TimeSpan.FromSeconds(1), RetryOptions = new CosmosRetryOptions { // 最大重试次数(针对限流及自定义可重试错误) MaxRetryAttemptsOnRateLimitedRequests = 3, // 重试间隔的最大等待时间,避免间隔过长 MaxRetryWaitTime = TimeSpan.FromSeconds(1), // 自定义重试策略,覆盖默认仅限流重试的逻辑 RetryPolicy = CosmosRetryPolicy.CreateCustomRetryPolicy( (exception, retryCount, delay) => { // 判断是否为可重试的异常:超时、服务不可用等 bool shouldRetry = exception is CosmosException cosmosEx && (cosmosEx.StatusCode == System.Net.HttpStatusCode.RequestTimeout || cosmosEx.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable) || exception is System.TimeoutException; // 校验总耗时是否未超过5秒(初始请求+重试延迟+重试请求) TimeSpan totalElapsed = delay * retryCount + TimeSpan.FromSeconds(1) * (retryCount + 1); return shouldRetry && totalElapsed < TimeSpan.FromSeconds(5); }) } } );
2. 结合Polly超时策略实现精准控制
如果你习惯用Polley统一管理超时逻辑,可以直接用Polly的TimeoutPolicy包裹Cosmos操作,强制限制整个流程的总时长,和你在Service Bus中的用法一致:
// 定义总超时策略:5秒 var totalTimeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(5)); // 用策略包裹Cosmos操作 await totalTimeoutPolicy.ExecuteAsync(async () => { Container container = cosmosClient.GetContainer("你的数据库名", "你的容器名"); await container.CreateItemAsync(new YourDocument()); });
这种方式能直接确保整个操作(包括Cosmos内部的所有重试、延迟)的总时长不超过5秒,逻辑更简洁统一。
内容的提问来源于stack exchange,提问作者Alasdair Stark
相关产品推荐
相关产品推荐

