WCF netTcp服务持续崩溃,需要重新启动服务器

WCF netTcp服务持续崩溃,需要重新启动服务器,wcf,f#,nettcpbinding,Wcf,F#,Nettcpbinding,我们有一个WCF netTcp服务,作为一些遗留应用程序进入我们开发的新服务平台的入口点。该服务本身不是很有趣,它基本上只有一行服务操作,将请求消息丢弃到邮箱中,供新平台处理。该服务通常一次可以正常工作数周,但有时在重新启动该服务(它在较大的windows服务中自托管)后,它会崩溃并拒绝重新启动,除非重新启动整个服务器 我们在非生产环境中启用了WCF跟踪,并且能够重新创建问题,因此我们有一些完整的问题跟踪日志,但到目前为止,它还没有帮助我们确定根本原因 我们看到的第一个异常是带有消息的Socke

我们有一个WCF netTcp服务,作为一些遗留应用程序进入我们开发的新服务平台的入口点。该服务本身不是很有趣,它基本上只有一行服务操作,将请求消息丢弃到邮箱中,供新平台处理。该服务通常一次可以正常工作数周,但有时在重新启动该服务(它在较大的windows服务中自托管)后,它会崩溃并拒绝重新启动,除非重新启动整个服务器

我们在非生产环境中启用了WCF跟踪,并且能够重新创建问题,因此我们有一些完整的问题跟踪日志,但到目前为止,它还没有帮助我们确定根本原因

我们看到的第一个异常是带有消息的
SocketException
,远程主机强制关闭了一个现有连接,本地错误代码为
2746
。这发生在SocketConnection.HandlerReceiveAsyncCompleted上。下一个异常(紧跟在跟踪之后)是
CommunicationException
表示套接字连接已中止。这可能是由于处理消息时出错、远程主机超过接收超时或基础网络资源问题造成的。本地套接字超时为“10675199.02:48:05.4775807”。

此后,任何使用WCF
ServiceHost
对象的尝试都会导致标准
通信对象System.ServiceModel.ServiceHost出现
CommunicationObjectFaultedException
,因为它处于故障状态,因此无法用于通信。重新启动WCF服务甚至整个windows服务会导致立即失败,但也会出现相同的异常

随后尝试自动重新启动WCF服务(使用新的
ServiceHost
对象)时,总会遇到另外两个异常。第一个是
AddressAlreadyInUseException
表示
在IP端点0.0.0.0:11300上已经有一个侦听器。如果有另一个应用程序正在侦听此端点,或者如果您的服务主机中有多个具有相同IP端点但绑定配置不兼容的服务端点,则可能会发生这种情况。
第二个是带有消息
实例的
ArgumentException
'PublisherService@net.tcp:| | localhost:11300 | PublisherService'已存在于计数器集中'e829b6db-21ab-453b-83c9-d980ec708edd'。 参数名称:InstanceName

作为参考,管理此WCF服务的Windows服务内的代码如下所示:

// Create a PublisherService to send WCF requests to the Publisher Actor's mailbox
let publisherService = PublisherService(fun request -> publisherActor <! request)

let rec initHost () =                        
    // Create a new WCF ServiceHost for the Publisher Service
    let host = new ServiceHost(publisherService, [| config.PublisherServiceUri |])
    host.AddServiceEndpoint(typeof<IPublisherService>.FullName, NetTcpBinding(SecurityMode.None), config.PublisherServiceUri) |> ignore

    // Log any WCF Service Faulted events and try to start a new ServiceHost
    host.Faulted |> Event.add (fun _ -> 
        log.errorf "Publisher Service '%s' faulted. Restarting in 10 seconds..." config.PublisherServiceUri
        // BUG: Always fails with CommunicationObjectFaulted exception -- probably shouldn't be here
        try host.Close ()
        with | ex -> log.errorx ex "Error closing faulted Service Host"
        // TODO: Do something smarter than just sleeping for 10 seconds before restarting the service host
        Async.Sleep 10000 |> Async.RunSynchronously
        // BUG:  This isn't tail-recursive, will probably blow the stack eventually
        initHost () |> ignore)

    // Start the WCF Service Host
    host.Open()
    log.debugf "Publisher Service '%s' started." config.PublisherServiceUri

initHost()
//创建PublisherService以将WCF请求发送到发布者参与者的邮箱
让publisherService=publisherService(fun请求->publisherActor.FullName,NetTcpBinding(SecurityMode.None),config.PublisherServiceUri)|>忽略
//记录所有WCF服务故障事件,并尝试启动新的ServiceHost
host.Faulted |>Event.add(乐趣->
log.errorf“发布服务器服务“%s”出现故障。10秒后重新启动…”config.PublisherServiceUri
//错误:总是失败,出现CommunicationObjectFaulted异常——可能不应该出现在这里
尝试主机关闭()
使用| ex->log.errorx ex“错误关闭故障服务主机”
//TODO:在重启服务主机之前,做一些比只睡10秒钟更聪明的事情
Async.Sleep 10000 |>Async.RunSynchronously
//错误:这不是尾部递归,可能最终会破坏堆栈
initHost()|>忽略)
//启动WCF服务主机
host.Open()
log.debugf“发布服务器服务“%s”已启动。”config.PublisherServiceUri
initHost()

我意识到这段代码有一些问题,但我不明白为什么即使重新启动整个Windows服务也不允许WCF服务干净地启动。一旦WCF服务开始运行,它似乎就可以无限期地正常运行,但是如果我们出于任何原因重新启动它,它就有可能进入这种状态,在这种状态之后,如果不重新启动服务器,它将变得完全不可恢复。如果有人能够就进一步排除潜在问题提供任何指导,或者知道可能导致这种行为的任何原因,我将非常感谢您的帮助

“IP端点0.0.0.0:11300上已存在侦听器”错误向我建议套接字仍处于
TIME\u WAIT
状态,您需要等待最多4分钟(通常)等待等待套接字关闭。有关更多详细信息,请参阅,其中有一个很好的解释(它基于Linux,但Windows上的底层TCP堆栈应该基本相同,因为Linux和Windows都必须实现RFC中指定的时间等待行为)。@rmunn谢谢,我将对此进行研究。@rmun如果这是问题所在,我会在TcpView的
TIME\u WAIT
中看到端口11300吗?要么
TIME\u WAIT
要么
CLOSE\u WAIT
;根据,区别在于
TIME\u WAIT
表示“此端关闭连接”,而
CLOSE\u WAIT
表示“远程端关闭连接”。无论哪种方式,TCP堆栈都必须等待四分钟才能允许重新使用该端口。@rmunn我在开发环境中对此进行了测试,但在TcpView中没有看到端口进入
TIME\u wait
CLOSE\u wait
。它直接从
收听
变为不出现在列表中。我还查看了一些生产日志,在WCF服务崩溃和重新启动Windows服务之间似乎有25分钟的间隔,但在服务重新启动后,问题仍然会立即出现。我们已经向微软开出了一张罚单,如果他们能帮我们找到答案,我会发布答案。