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

时间:2012-12-12 11:30:58

标签: .net wcf silverlight polling pollingduplexhttpbinding

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

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

一般流程:

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

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

  3. Fiddler仅显示投票消息的空404响应
  4. 然后提出客户端Channel Faulted事件
  5. 我在尝试重新连接SL客户端后出现这样的错误,单个重新连接重试流程:

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

      服务器:

      • 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>
      

2 个答案:

答案 0 :(得分:3)

如果一切似乎都运行良好,那么这可能是网络基础设施/配置问题(例如dns配置)。在本地运行或使用ip地址而不是主机名时,是否会遇到同样的问题?

如果在IIS中的站点上配置了多个绑定,也可能出现类似问题(有关详细信息,请参阅此处:http://blogs.msdn.com/b/rampo/archive/2008/02/11/how-can-wcf-support-multiple-iis-binding-specified-per-site.aspx

另一件事是你如何从服务器传达给客户。如果您在循环中迭代客户端并逐个调用回调方法,那么您可能会获得显示为404的超时。通常应该在后台线程上调用回调(每个客户端一个)。

根据您的通信方式,这也可能是由死锁引起的(当UI线程涉及向服务发送/接收消息/回调时)。

答案 1 :(得分:1)

在调查此StackOverflow帖子Static constructor called twice for PerSession WCF service上描述的问题时,我发现当我为基础Polling Duplex切换IIS配置以使用单个工作进程而不是AppPool时,2开始工作稳定如前所述2。我不确定为什么404之前已经设置了,因为我没有这台服务器,但无论如何这就是我现在所拥有的 - 在同一台机器上启动的多个Silverlight客户端工作稳定并且民意调查民意调查并且没有{{1错误,所有客户端重新连接1尝试IIS重新启动并回收...

有关详细信息,请参阅Performance Application Pool Settings

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

因此,设计中的轮询双工不能在单个IIS服务器和AppPool的范围内的多个进程中进行扩展,换句话说,如果您有多个工作进程 - 这是WebGarden环境和duplex is not scalable across web farms and gardens