我有一个实现
System.ServiceModel.ClientBase<TChannel>
的 C# 客户端,用于与 SOAP API 进行通信。
我希望客户端在发生超时时自动重试请求。
我想我可以使用像 Polly 这样的库来创建具有重试策略的 HttpClient 实例。
但是,我无法弄清楚如何使用该 HttpClient 实例化 WCF 客户端。
我也不确定我是否应该使用完全不同的方法,例如创建一个
IEndpointBehavior
。
看起来有一个可以重写的实例方法和可以实现的静态部分方法,但是我找不到任何如何正确使用它们通过实例化的 HttpClient 来实现重试的示例或通过其他机制。
我已经搜索了构建客户端的文档。 有关于使用通道工厂
的部分,但它似乎也没有提供 HttpClient 的机制。 预期异常的文档特别提到了
CreateChannel
ConfigureEndpoint
。 我知道我可以做到这一点,并且我知道我可以创建一个装饰器,以类似的逻辑包装所有客户端调用。我只是认为这不是正确的方法。
任何为我指明正确方向的帮助将不胜感激。
如果是
TimeoutException
RetryOnTimeout(client => client.MethodToRetryOnTimeout());
会注册一个
HttpClient
,即 AddPolicyHandler
。它基本上覆盖了PolicyHttpMessageHandler
:DelegatingHandler
我已经有一段时间没有使用 WCF 了,但如果我没记错的话,最接近的就是客户端消息拦截器(SendAsync
)。尽管它是可行
,但不幸的是它并不容易实现。另一种选择是使用
Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken);
。基本上,在这里,您可以重写 IClientMessageInterceptor
方法,并使用触发
RealProxy
和 Invoke
的策略来装饰 MethodBase
的
Invoke
调用。这种方法的问题是
TimeoutException
在 .NET Core(或其后继者)中不可用。
因此,唯一的选择是包装自己的方法调用。这个可以做吗使用通用静态方法(在您的示例中为
CommunicationException
)
RealProxy
派生类
RetryOnTimeout
ClientBase
上花了更多时间后,我遇到了 这篇迁移文章
class ResilientSampleClient: ClientBase<ISampleClient>, ISampleClient
{
private readonly IRetryPolicy retryPolicy = Policy
.Handle<TimeoutException>()
.Or<CommunicationException>()
.WaitAndRetry(3, _ => TimeSpan.FromSeconds(1));
public ResilientSampleClient(): base(binding, endpointAddress) {}
public void MethodToRetryOnTimeout()
=> retryPolicy.Execute(base.Channel.MethodToRetryOnTimeout);
}
代替。
我还没有测试过这段代码,但是根据迁移文档,基于RealProxy
的解决方案可以重写如下:
wcf客户端实例可以参考本文档。它详细介绍了创建客户端的详细信息。