Polly重试策略执行时URL参数重复叠加问题求助
Polly重试策略执行时URL参数重复叠加问题求助
嘿,我最近在使用Polly重试策略时碰到了一个特别诡异的问题,想请各位大佬帮忙分析下原因!
先给大家看下我的Polly策略配置代码:
IAsyncPolicy retryPolicy = Policy .Handle<HttpRequestException>(e => !e.IsBadRequest()) .WaitAndRetryAsync( Backoff.DecorrelatedJitterBackoffV2("00:00:01", 5), onRetry: (response, timeSpan, retryCount, context) => { if (!context.TryGetLogger(out var logger)) { return; } logger.LogWarning($"Retrying call {retryCount} with timespan: {timeSpan} due to: {response.Message}"); });
这个策略我是作为单例注入到业务类里使用的,调用方式如下:
var context = new Context($"API-call-{Guid.NewGuid()}", new Dictionary<string, object> { { "logger", _logger }, }); await _resiliencePolicy.ExecuteAsync(async ctx => await _apiClient.Post.Delete(2), context);
问题现象:每当触发重试时,原本的请求URL https://someurl.com/post/2 会变成 https://someurl.com/post/22,而且每多一次重试,末尾的2就会多一个——比如第10次重试时,URL直接变成了https://someurl.com/post/2222222222,完全偏离预期了!
有没有大佬能帮我梳理下这到底是哪里出问题了?感激不尽!
可能的原因分析
大概率问题不在Polly本身,而是你的_apiClient.Post实例存在状态复用的情况:
_apiClient.Post这个对象可能维护了内部的请求路径状态,每次调用Delete(2)时,不是基于原始基础URL重新拼接完整路径,而是把参数2追加到了已有的路径后面,导致每次重试都叠加参数。- 简单说就是:这个客户端实例不是“无状态”的,第一次调用后它的请求路径已经变成了
/post/2,第二次重试调用时又在这个基础上追加了2,就变成了/post/22,以此类推。
解决方案建议
检查并修复API客户端的实现
确保Delete方法每次调用都重新构造完整URL,不要依赖实例内部的状态。示例如下:// 正确的无状态实现示例 public class PostClient { private readonly string _baseUrl; public PostClient(string baseUrl) { _baseUrl = baseUrl; } public async Task Delete(int id) { // 每次调用都重新拼接完整URL,不修改实例状态 var requestUrl = $"{_baseUrl}/post/{id}"; // 发送HTTP请求的逻辑... } }每次重试使用新的客户端实例
如果无法修改现有客户端的实现,可以在重试委托里每次创建新的客户端实例,避免状态复用:await _resiliencePolicy.ExecuteAsync(async ctx => { // 每次重试都初始化一个干净的客户端实例 var freshApiClient = new ApiClient("https://someurl.com"); await freshApiClient.Post.Delete(2); }, context);确保委托内的请求逻辑是无状态的
把构造请求的逻辑完全放在ExecuteAsync的委托中,确保每次重试都执行全新的请求构造流程,而不是复用之前的请求对象或客户端状态。
验证小技巧
你可以先脱离Polly,单独多次调用_apiClient.Post.Delete(2),观察每次的请求URL是否会叠加。如果叠加的话,那就能实锤是客户端的状态问题,和Polly无关——Polly只是忠实地重复执行了你提供的委托逻辑而已。
备注:内容来源于stack exchange,提问作者Ben D
相关产品推荐
相关产品推荐

