我在JsonServiceClient上创建了一个包装类,并在那里实现了重试,但我想知道这种方法的最佳解决方案是什么。
我同意你的方法。扩展JsonServiceClient并在那里实现重试逻辑是可重用性和可维护性最好的方法,前提是你已经实现了下面这样的内容。
扩展JsonServiceClient
扩展JsonServiceClient以便你可以整合自己的重试逻辑。然后,你可以在代码中轻松地重复使用它,而不需要每次想要进行请求时都使用while和计数器。
如果你在这里看到{{link1:
JsonServiceClientBase.cs
}}代码,你会注意到所有动词方法,例如
Get<TResponse>
Post<TResponse>
...
Put
等,都通过
Send<TResponse>(object request)
方法调用。
因此,通过覆盖此方法,我们可以在所有动词上轻松实现重试功能,而无需更改其用法。
public class MyJsonServiceClientWithRetry : JsonServiceClient
{
public MyJsonServiceClientWithRetry()
{
}
public MyJsonServiceClientWithRetry(int retryAttempts)
{
RetryAttempts = retryAttempts;
}
public MyJsonServiceClientWithRetry(string baseUri) : base(baseUri)
{
}
public MyJsonServiceClientWithRetry(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri)
{
}
public int RetryAttempts { get; set; }
public override TResponse Send<TResponse> (string httpMethod, string relativeOrAbsoluteUrl, object request)
{
int attempts = RetryAttempts;
while(true)
{
attempts--;
try {
return base.Send<TResponse> (httpMethod, relativeOrAbsoluteUrl, request);
} catch (WebServiceException webException) {
if(attempts == 0 || webException.StatusCode == 400 || webException.StatusCode == 401)
throw;
} catch (Exception exception) {
if(attempts == 0)
throw;
}
}
}
}
使用方法:
- 将对
JsonServiceClient
的引用替换为 MyJsonServiceClientWithRetry
- 设置尝试次数
- 像平常一样使用客户端。(在重试次数超过限制后,使用
try/catch
块捕获异常)
var client = new MyJsonServiceClientWithRetry ("http://localhost:8080") {
RetryAttempts = 3,
Timeout = new TimeSpan(0, 0, 30)
};
try
{
var myRequestDto = new MyRequest {
Name = "John Smith"
};
var response = client.Get<MyResponse>(myRequestDto);
} catch(Exception ex) {
}
注意事项:
如果出现状态码为400或401的WebServiceException
异常,我不会重试,因为不改变请求再次尝试似乎是多余的。当然,您可以自定义此逻辑。
如果连接超时,则会抛出超时错误作为WebException
。如果您想要特别处理此情况。
希望这有所帮助。