【问题标题】:WCF Silverlight client getting 404 not found response for poll messageWCF Silverlight 客户端收到 404 未找到轮询消息的响应
【发布时间】:2012-11-30 02:22:51
【问题描述】:

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

!有趣的是,当使用MaxMessagesPerPollduplex 模式和解决方案描述为here 和here 时,这个问题就像已知的Silverlight 4 错误,但我使用的是SingleMessagePerPoll 模式。无论如何,我按照建议尝试使用ClientStack,但没有任何改变。

一般流程:

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

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

  3. Fiddler 仅显示空的 404 对投票消息的响应
  4. 然后引发客户端 Channel Faulted 事件

我正在尝试在出现此类故障后重新连接 SL 客户端,单次重新连接重试流程:

  1. 处理Faulted事件
  2. 取消订阅所有频道事件,例如Closed/Closing/Opened/Opening
  3. 使用try { close } catch { abort }以正确的方式关闭频道
  4. 下面的所有内容都在一个新的线程轮询线程中:(我发现这有点稳定 - see this article)
  5. 等待 45-70 秒
  6. 使用相同的DuplexChannelFactory<T> 实例创建一个新频道,订阅所有频道事件,仅用于记录目的
  7. 执行 WCF 服务方法

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

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

一般信息:

  • .NET Framework 4.0
  • 轮询双工
  • 异步 WCF 方法
  • IIS 6.0 托管的 WCF 服务
  • Silverligth 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>

【问题讨论】:

标签: .net wcf silverlight polling pollingduplexhttpbinding


【解决方案1】:

如果一切似乎都正常,那么这可能是网络基础设施/配置问题(例如 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 线程参与发送/接收消息/与服务之间的回调时)。

【讨论】:

  • 感谢您的链接,现在阅读。在 IIS 中,一个站点有大约 15 个 VD,有些站点具有相同的投标,因为运行相同的服务但​​在不同的端口上。 1)关于客户端响应 - 我使用 PerSession 服务实例模式,因此每个客户端连接单个服务
  • 我们在 web.config 中将 multipleSiteBindingsEnabled 设置为 true
  • 关于后台线程中的回调,您确定这对无 UI 的 WCF 服务有意义吗?我还发现如果 Silverligth 客户端无法进行异步回调?!无论如何,我会手动分派到 UI 线程,并且没有异常,因为我启用了所有的显示
  • 如果您在同一个线程上处理回调,那么服务器将需要等待每个回调通过可能会阻塞一段时间(特别是如果您可能会从某些客户端获得超时)。如果您在新线程上执行每个回调,那么您基本上可以执行“触发并忘记”并返回处理传入消息。
  • 另外,当你调用服务器时,可能会有这样的场景,服务器在它接收到消息的同一个线程上回调,线程等待客户端响应,同时客户端调用另一个方法无法处理,因为服务器线程正忙于等待回调 - 您可能会在此处出现死锁,直到其中一个连接超时。再说一次,这取决于您如何设置服务。
【解决方案2】:

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

详情请见Performance Application Pool Settings

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

因此,Polling Duplex 的设计无法跨单个 IIS 服务器和 AppPool 范围内的多个进程进行扩展,换句话说,如果您有超过 1 个工作进程 - 这是 WebGarden 环境和duplex is not scalable across web farms and gardens

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 2012-06-04
    • 2020-05-13
    • 2015-11-23
    相关资源
    最近更新 更多