最终,WCF 双工 Silverlight 4 客户端开始收到404 Not Found
轮询消息错误,轮询从 WCF 服务发送到 Silverlight 客户端后,有时会在第二轮轮询时发生这种情况,有时连接工作数小时甚至数天,但大部分在第一分钟失败。
!有趣的是,这个问题就像使用MaxMessagesPerPoll
双工模式时已知的 Silverlight 4 错误一样,这里和这里描述了解决方案,但我使用的是SingleMessagePerPoll
模式。无论如何,我尝试ClientStack
按照建议使用,但没有任何改变。
一般流程:
- SL 客户端执行 WCF 服务方法,收到响应
- 然后立即SL 客户端开始向服务发送轮询消息,然后获取第二个或 Ns 轮询消息的异常
System.Net.WebException:远程服务器返回错误:NotFound
- Fiddler 仅显示
404
民意调查消息的空响应 - 然后引发客户端 Channel Faulted 事件
我正在尝试在出现此类故障后重新连接 SL 客户端,单次重新连接重试流程:
- 处理
Faulted
事件 - 取消订阅所有频道事件,例如
Closed/Closing/Opened/Opening
- 使用正确的方式关闭频道
try { close } catch { abort }
- 所有以下内容都在一个新的线程投票线程中:(我发现这有点稳定 -请参阅这篇文章)
- 等待 45-70 秒
- 使用同一个
DuplexChannelFactory<T>
实例创建一个新频道,订阅所有频道事件,仅用于记录目的 - 执行 WCF 服务方法
经过 1-10 次重试(约 1-10 分钟)后,客户端最终连接到服务器并继续正常轮询。
在 WCF 服务日志中,我看到它得到了所有客户端请求,没有任何异常处理,所以 Silverlight 客户端似乎发生了一些事情。
基本信息:
- .NET 框架 4.0
- 轮询双工
- 异步 WCF 方法
- IIS 6.0 托管的 WCF 服务
- Silverlight 4 客户端
- 客户端操作系统:Windows XP SP2
- 服务器操作系统:Windows 2003 R2 SP2
- NTLM 身份验证
- 双工模式:SingleMessagePerPoll
- 还有一个 WCF 服务在我的服务开始工作之前执行请求/回复,它不使用双工连接
- 在 SL 客户端服务上,我将所有内容都记录到 UI 中,以便查看所有事件流并为每个特定事件留出时间
- IIS 日志、服务器事件日志中没有错误
客户:
var binaryBinding = new BinaryMessageEncodingBindingElement();
binaryBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
var httpbindingElement = new HttpTransportBindingElement
{
MaxReceivedMessageSize = 131072
};
var pollingDuplexBindingElement = new PollingDuplexBindingElement
{
ClientPollTimeout = new TimeSpan(0, 0, 1, 30),
InactivityTimeout = new TimeSpan(0, 8, 0, 0),
};
_binding = new CustomBinding(
pollingDuplexBindingElement,
binaryBinding,
httpbindingElement)
{
SendTimeout = new TimeSpan(0, 0, 0, 45),
CloseTimeout = new TimeSpan(0, 0, 0, 25),
ReceiveTimeout = new TimeSpan(0, 8, 0, 0),
OpenTimeout = new TimeSpan(0, 0, 0, 45)
};
httpbindingElement.AuthenticationScheme = AuthenticationSchemes.Negotiate;
var endpoint = new EndpointAddress(_endpointAddress);
_channelFactory = new DuplexChannelFactory<TWebService>(
new InstanceContext(instanceOfClientServiceClass),
_binding,
endpoint);
// then this factory used to create a new channels
// Also for a new channel I'm setting OpTimeout
var contextChannel = newChannel as IContextChannel;
if (contextChannel != null)
{
contextChannel.OperationTimeout = TimeSpan.FromSeconds(45);
}
服务器:
- WCF、PerSession、多线程
- 一切都是线程安全的
- 执行时没有服务器服务异常
- 很多日志记录,所以我看到了服务上发生了什么
- 所有 WCF 跟踪都使用 switchValue 启用
All
,没有任何可疑之处
<binding name="customName"
sendTimeout="00:01:00"
receiveTimeout="08:00:00"
openTimeout="00:01:00"
closeTimeout="00:00:35">
<pollingDuplex
inactivityTimeout="08:00:00"
serverPollTimeout="00:01:00" />
<binaryMessageEncoding />
<httpTransport authenticationScheme="Ntlm"
maxReceivedMessageSize="131072">
</httpTransport>
</binding>
<behavior name="customBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling
maxConcurrentCalls = "500"
maxConcurrentSessions = "500"
maxConcurrentInstances = "500" />
</behavior>