WCF Silverlight客户端获取404未找到的轮询消息响应

sll*_*sll 7 .net silverlight wcf polling pollingduplexhttpbinding

最终WCF双工Silverlight 4客户端开始获取404 Not Found轮询消息的错误,在轮询从WCF服务发送到Silverlight客户端之后立即发生,有时这种情况发生在第二次轮询中,有时连接工作数小时甚至数天,但大多数在第一分钟失败.

!有趣的是,这个问题就像使用MaxMessagesPerPoll双工模式时已知的Silverlight 4错误一样,这里这里描述解决方案,但我正在使用SingleMessagePerPoll模式.ANyway我ClientStack按照建议尝试使用,但没有任何改变.

一般流程:

  1. SL客户端执行WCF服务方法,收到响应
  2. 然后, SL客户端立即开始向服务发送轮询消息,然后获取第二个或Ns轮询消息的异常

    System.Net.WebException:远程服务器返回错误:NotFound

  3. Fiddler仅显示404轮询消息的空响应
  4. 然后客户端Channel Faulted事件提出

我试图在出现这样的故障后重新连接SL客户端,单个重新连接重试流程:

  1. 处理Faulted事件
  2. 取消订阅所有频道活动,例如 Closed/Closing/Opened/Opening
  3. 使用正确的方式关闭通道 try { close } catch { abort }
  4. 所有下面的新线程民意调查线程:(我觉得这个工作稍微稳定一点 - 看看这篇文章)
  5. 等待45-70秒
  6. 使用相同的DuplexChannelFactory<T>实例创建新通道,仅为了记录目的订阅所有通道事件
  7. 执行WCF服务方法

1-10次重试(~1-10分钟)后,客户端最终连接到服务器并继续正常轮询.

在WCF服务日志中,我看到它获得了所有cleint请求,没有任何异常处理,因此似乎Silverlight客户端发生了一些事情.

基本信息:

  • .NET Framework 4.0
  • PollingDuplex
  • 异步WCF方法
  • IIS 6.0托管WCF服务
  • Silverligth 4客户
  • 客户端操作系统:Windows XP SP2
  • 服务器操作系统:Windows 2003 R2 SP2
  • NTLM身份验证
  • DuplexMode: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);
}
Run Code Online (Sandbox Code Playgroud)

服务器:

  • 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>
Run Code Online (Sandbox Code Playgroud)

sll*_*sll 1

在调查此 StackOverflow 帖子中描述的问题时,静态构造函数为 PerSession WCF 服务调用了两次,我发现Polling Duplex当我将IIS底层配置切换为AppPool使用单个工作进程而不是2之前指定时,它开始稳定工作。我不知道为什么2之前设置,因为我不拥有这台服务器,但无论如何,这就是我现在所拥有的 - 在同一台计算机上启动的多个 Silverlight 客户端工作稳定,轮询轮询,没有错误,所有客户端在尝试后404重新连接1IIS 重新启动并回收...

有关更多详细信息,请参阅性能应用程序池设置

TL;DR: 当 IIS 托管的 WCF 驻留在具有多个工作进程的 AppPool 中时 - 轮询双工变得不稳定。因此,在高负载的情况下,IIS 启动了第二个进程,并开始在第二个进程中创建 WCF 服务实例,所以我遇到了这样的情况:在一个进程中创建客户端会话,但似乎轮询有时会到达另一个进程,而该进程不知道当前的情况连接/会话因此开始拒绝此类消息和整个连接故障。

因此,轮询 Duplex 的设计在单个 IIS 服务器和 AppPool 范围内的多个进程之间不可扩展,换句话说,如果您有超过 1 个工作进程 - 这是 WebGarden 环境,并且duplex 不可在 Web 场和花园之间扩展