代码之家  ›  专栏  ›  技术社区  ›  knightpfhor

Azure WCF主机在一个实例重新启动时导致通信错误

  •  0
  • knightpfhor  · 技术社区  · 15 年前

    我们有一个托管在中的WCF主机和使用net 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;
    }
    

    我的期望是,我们正在创建一个新的代理,每次调用这个浏览函数时都会有一个新的通道和一个新的连接。

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

    我目前的工作假设是,在幕后的某个地方,WCF客户机正在打开一个与不再存在的实例的连接,尽管我读到的所有内容都说它不应该存在。

    除了捕获这个特定错误并重试之外,还有什么可以避免这个问题的吗?有什么模式可以重试客户端调用吗?如果我真的要重试,我怎么能确保这个不可靠的连接真的被破坏了呢?到目前为止,我的尝试还不是很成功。

    1 回复  |  直到 15 年前
        1
  •  0
  •   knightpfhor    15 年前

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

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

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