使用 WCF 和 TCP 保持连接? [英] KeepAlive with WCF and TCP?

查看:24
本文介绍了使用 WCF 和 TCP 保持连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个托管高级 WCF 服务的 Windows 服务,该服务通过 TCP(netTCP) 与 protobuf.net 进行通信,有时还使用证书.

I have a Windows Service hosting an advanced WCF service that communicates over TCP(netTCP) with protobuf.net, some times also with certificates.

receiveTimeout 设置为无穷大,不会因为不活动而断开连接.但据我所知,无论如何连接都可能会被丢弃,所以我创建了一个简单的两路 keepalive 服务方法,客户端每 9 分钟调用一次以保持连接活动.连接永不中断非常重要.

The receiveTimeout is set to infinite to never drop the connection due to inactivity. But from what I understand the connection could be dropped anyway so I have created a simple two way keepalive service method that the client is calling every 9 min to keep the connection alive. It's very important that the connection never breaks.

这是正确的方法吗?或者我是否可以因为 receiveTimout 设置为无限而简单地删除我的 keep live?

Is this the correct way? Or could I simply remove my keep live because the receiveTimout is set to infinite?

WCF 服务的当前 app.config :http://1drv.ms/1uEVKIt

Edit : Current app.config for WCF service : http://1drv.ms/1uEVKIt

推荐答案

没有.这被广泛误解,不幸的是,那里有很多错误信息.

No. This is widely misunderstood, and unfortunately there is much misinformation out there.

首先,Infinite"是一种半有效值.有两个特殊的配置序列化程序可以将Infinite"转换为 TimeSpan.MaxValueint.MaxValue(所以无论如何它们都不是真正的无限"),但不是WCF 中的一切似乎都认识到这一点.因此,最好使用时间值明确指定超时.

First, "Infinite" is a sort of semi-valid value. There is are two special config serializers that convert "Infinite" to either TimeSpan.MaxValue or int.MaxValue (so they're not really "infinite" anyways), but not everything in WCF seems to recognize this. So it's always best to specify your timeouts explicitly with time values.

其次,您的服务中不需要keepalive"方法,因为 WCF 提供了所谓的可靠会话".如果您添加 <reliableSession enabled="true"/> 那么 WCF 将通过基础设施消息"提供它自己的保持活动机制.

Second, you don't need a "keepalive" method in your service, since WCF provides what's called a "reliable session". If you add <reliableSession enabled="true" /> then WCF will provide it's own keep alive mechanism through "infrastructure messages".

通过拥有自己的keepalive"机制,您可以有效地将服务的负载加倍,而且实际上您可能会产生比它解决的问题更多的问题.

By having your own "keepalive" mechanism, you're effectively doubling the load on your service and you can actually create more problems than it solves.

第三,当使用可靠会话时,您使用reliableSessioninactivityTimeout 设置.这有两件事.首先,它控制发送基础设施(keepalive)消息的频率.它们以超时值的一半发送,因此如果您将其设置为 18 分钟,则它们将每 9 分钟发送一次.其次,如果在不活动超时内没有接收到基础设施或操作消息(即属于您的数据合同的一部分的消息),则连接将中止,因为可能存在问题(一侧崩溃、存在网络问题等)..).

Third, when using a reliable session, you use the inactivityTimeout setting of reliableSession. This does two things. First, it controls how frequently infrastructure (keepalive) messages are sent. They are sent at half the timeout value, so if you set it to 18 minutes, then they will be sent every 9 minutes. Secondly, if no infrastructure or operation messages (ie messages that are part of your data contract) are received within the inactivity timeout, the connection is aborted because there has likely been a problem (one side has crashed, there's a network problem, etc..).

receiveTimeout 是连接中止前无法接收到操作消息的最长时间(默认为 10 分钟).将其设置为一个较大的值(Int32.MaxValue 大约为 24 天)保持连接正常,将 inactivityTimeout 设置为较小的值(同样,默认值为 10 分钟)(设置为小于网络路由器从不活动状态断开连接的最长时间的 2 倍的时间)保持连接有效.

receiveTimeout is the maximum amount of time in which no operation messages can be received before the connection is aborted (the default is 10 minutes). Setting this to a large value (Int32.MaxValue is somewhere in the vicinity of 24 days) keeps the connection tacked up, setting inactivityTimeout to a smaller value (again, the default is 10 minutes) (to a time that is smaller than 2x the maximum amount of time before network routers will drop a connection from inactivity) keeps the connection alive.

WCF 为您处理所有这些.然后,您只需订阅 Connection Aborted 消息即可了解连接何时因真正原因(应用崩溃、网络超时、客户端断电等)而断开,并允许您重新创建连接.

WCF handles all this for you. You can then simply subscribe to the Connection Aborted messages to know when the connection is dropped for real reasons (app crashes, network timeouts, clients losing power, etc..) and allows you to recreate the connections.

此外,如果您不需要有序消息,请设置ordered="false",因为这会大大减少可靠会话的开销.默认为真.

Additionally, if you don't need ordered messages, set ordered="false", as this greatly reduces the overhead of reliable sessions. The default is true.

注意:在 inactivityTimeout 过期(或您尝试使用连接)之前,您可能不会收到连接中止事件.请注意这一点,并相应地设置超时.

Note: You may not receive a connection aborted event until the inactivityTimeout has expired (or you try to use the connection). Be aware of this, and set your timeouts accordingly.

互联网上的大多数建议是将 receiveTimeout 和 inactivityTimeout 都设置为 Infinite.这有两个问题,首先是基础设施消息没有及时发送,所以路由器会断开连接……迫使你自己做keepalive.其次,较大的不活动超时意味着它无法识别连接何时合法断开,您必须依靠 ping 中止来了解何时发生故障.这完全没有必要,实际上甚至会使您的服务更加不可靠.

Most recommendations on the internet are to set both receiveTimeout and inactivityTimeout to Infinite. This has two problems, first infrastructure messages don't get sent in a timely manner, so routers will drop the connection... forcing you to do your own keepalives. Second, the large inactivity timeout means it won't recognize when a connection legitimately drops, and you have to rely on on that ping aborting to know when a failure occurs. This is all completely unnecessary, and can in fact even make your service even more unreliable.

另见:我如何正确配置 WCF NetTcp 双工可靠会话?

这篇关于使用 WCF 和 TCP 保持连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆