0

我对 Azure 中的 WCF 主机有一个相当具体的问题。请耐心等待我描述情况。

我们有一个 WCF 主机托管在使用网络 TCP 绑定的 Azure 辅助角色中。我们有两个运行此工作者角色的实例来提供冗余。由于与我们的问题无关的原因,我们通过每小时更改配置设置来强制重启这些实例。由于升级域,一个实例在第二个实例之前重新启动,这意味着我们始终至少有一个实例在运行。

我们的客户端代码(也在 Azure 上运行,但我认为它在哪里并不重要)看起来与此非常相似(更改了函数名称以夸大其词):

public BrowseResults Browse(BrowseParameters parameters)
{
    using (Proxy client = CreateProxyWithBindingsAndEndPoints())
    {
        return client.Browse(parameters);
    }
}

private Proxy CreateProxyWithBindingsAndEndPoints()
{
    var binding = new NetTcpBinding(SecurityMode.Transport);

    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
    binding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;

    var epAddress = new EndpointAddress(
        new Uri("http://myapp.cloudapp.net:1000/myservice"),
        new DnsEndpointIdentity("my identity"),
        new AddressHeaderCollection());

    var client = new Proxy(binding, epAddress);

    client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate();

    return client;
}

我对此的期望是,每次我们调用这个 Browse 函数时,我们都会创建一个新的代理,一个新的通道和一个新的连接。

我们的问题发生在其中一个实例重新启动时System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state出现错误。现在,对于每个重新启动的主机,我们只会得到其中一个错误,但这仍然是一个我们不能没有的错误。

我目前的工作假设是,WCF 客户端在引擎盖下的某处保持与不再存在的实例的连接,尽管事实上我读过的所有内容都表明它不应该存在。

除了捕获这个特定错误并重试之外,我还能做些什么来避免这个问题?是否有任何模式可以重试客户端调用?如果我重试,我怎样才能确保这个狡猾的连接真的被取消了?到目前为止,我的重试尝试并不是很成功。

4

1 回答 1

0

经过相当多的调查后,问题似乎不在客户端,而是在服务器。辅助角色正在 OnRun 中启动 WCF 主机。问题是,当工作角色到达 OnRun 事件时,它已经向负载均衡器发出信号,表明它已准备好接收网络流量。看来宿主还没有真正开始,所以还没有真正准备好。

解决方案是将启动 WCF 主机的代码移至 OnStart 方法。

我们还创建了一些非常不错的 WCF 客户端重试代码。现在我们似乎不需要了。

于 2010-10-22T03:47:34.150 回答