我在 JsonServiceClient 上创建了包装类并在那里实现重试,但我想知道这种方法的最佳解决方案是什么。
我同意你的做法。扩展 JsonServiceClient 并实现您的重试逻辑,这是实现可重用性和可维护性的最佳方法,前提是您已经实现了如下所示的内容。
扩展JsonServiceClient
扩展JsonServiceClient,以便您可以合并自己的重试逻辑。然后它很容易在您的代码中重用,而无需在每次您想要发出请求时使用while 和计数器。
如果您在此处看到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)
{
}
// Retry attempts property
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) {
// Throw the exception if the number of retries is 0 or we have made a bad request, or are unauthenticated
if(attempts == 0 || webException.StatusCode == 400 || webException.StatusCode == 401)
throw;
} catch (Exception exception) {
// Throw the exception if the number of retries is 0
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"
};
// This request will be attempted 3 times (if there is an exception)
var response = client.Get<MyResponse>(myRequestDto);
// Do something with response ...
} catch(Exception ex) {
// Exception thrown here after 3 attempts (or immediately if status code is 400 / 401)
}
注意事项:
如果WebServiceException 抛出状态码为 400 或 401,我不会重试,因为在不更改它的情况下再次尝试此请求似乎是多余的。显然你可以自定义这个逻辑。
如果连接超时,则会将超时错误作为WebException 抛出。如果您想专门处理这种情况。
希望对你有帮助。