Azure虚拟机创建失败(StatusCode:TooManyRequests):重试策略问题咨询
问题描述
- 以10秒间隔重试6次创建Azure虚拟机,仍收到
TooManyRequests错误,错误详情如下:
Failed with StatusCode: TooManyRequests RequestMessage: Method: PUT, RequestUri: 'https://management.azure.com/subscriptions/aaa-bbb-ccc-ddd/resourceGroups/reqource_grp/providers/Microsoft.Compute/virtualMachines/VM_NAME?api-version=2022-03-01', Version: 1.1, Content: System.Net.Http.StringContent, Headers: { Accept: application/json Authorization: Bearer "" traceparent: 00-14a9ce9cba751f4cfb217ec0b8991ede-b1b327a3be820f60-00 Content-Type: application/json; charset=utf-8 Content-Length: 1494 } Content: System.Net.Http.HttpConnectionResponseContent ReasonPhrase: Headers Cache-Control: no-cache Pragma: no-cache Retry-After: 10 x-ms-failure-cause: gateway x-ms-request-id: 345672-331f-4c6a-becc-3f98a9459a5c x-ms-correlation-request-id: 34563cf-331f-4c6a-becc-3f98a9459a5c x-ms-routing-request-id: 20240719T104204Z:675a93cf-331f-4c6a-becc-3f98a9459a5c Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Cache: CONFIG_NOCACHE X-MSEdge-Ref: Ref A: 316D2AEF72A1434BBFA503FB3AFC2936 Ref B: AMS231032609023 Ref C: 2024-07-19T10:42:04Z Date: Fri, 19 Jul 2024 10:42:03 GMT
- 当前使用的Polly重试策略代码:
TimeSpan timeBetweenRetryForRequestUnitLimit = TimeSpan.FromSeconds(10); int maxAttemptsToRetry = 6; Policy.HandleResult<HttpResponseMessage>(response => !response.IsSuccessStatusCode) .WaitAndRetryAsync(maxAttemptsToRetry, retryAttempt => { log.LogInformation("Success Code Failure Attempt: {retryCount} Payload: {text}", retryAttempt, text); return timeBetweenRetryForRequestUnitLimit; });
- 补充:响应中未找到
x-ms-ratelimit-remaining-subscription-writes请求头
解决方案
1. 优先遵循Retry-After头动态调整重试间隔
响应中已返回Retry-After: 10,但固定间隔无法适配Azure动态变化的限流规则,后续请求的等待时间可能需要更长。修改策略,从响应头提取官方指定的等待时间:
Policy.HandleResult<HttpResponseMessage>(response => response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) .WaitAndRetryAsync(maxAttemptsToRetry, (retryAttempt, response, context) => { log.LogInformation("TooManyRequests Attempt: {retryCount}", retryAttempt); // 提取Retry-After值,无值则用指数退避兜底 if (response.Result.Headers.TryGetValues("Retry-After", out var values) && int.TryParse(values.First(), out int retryAfterSeconds)) { return TimeSpan.FromSeconds(retryAfterSeconds); } return TimeSpan.FromSeconds(10 * retryAttempt); });
注意:仅针对TooManyRequests错误重试,避免对参数错误等无法通过重试解决的问题无效重试。
2. 改用指数退避策略
固定10秒间隔易持续触发限流,改用指数退避(如第1次10秒、第2次20秒、第3次40秒...),给Azure足够的配额恢复时间:
Policy.HandleResult<HttpResponseMessage>(response => response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) .WaitAndRetryAsync(maxAttemptsToRetry, retryAttempt => { log.LogInformation("TooManyRequests Attempt: {retryCount}", retryAttempt); return TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 5); // 起始5秒,每次翻倍 });
3. 理解x-ms-ratelimit-remaining-subscription-writes头缺失原因
该头仅在未触发限流的成功响应中返回,收到TooManyRequests时Azure不会返回剩余配额,属于正常行为。若需提前监控配额,需在成功请求中捕获该头的值,提前调整请求频率。
4. 排查并发请求来源
确认当前订阅/资源组下是否有其他自动化操作(如批量创建VM、部署脚本)同时执行,这些操作会消耗订阅级请求配额。如有,需协调执行时间,降低并发量。
5. 调整重试参数
若业务允许,可适当增加最大重试次数(如至10次)或设置最大等待时间上限,避免过早放弃请求。
内容的提问来源于stack exchange,提问作者Rihab Kasim
相关产品推荐
相关产品推荐

