Reputation: 93444
Please excuse the Obvious Self-Q/A, but this information is widely misunderstood, and almost always incorrectly answered. So I Wanted to place this information here for people searching for a definitive answer to this problem.
Even so, there's still some information I haven't been able to nail down. I will put this towards the end of the question (skip to that if you are not interested in the preamble).
There are many questions and answers regarding this topic, and nearly all of them suggest setting inactivityTimeout="Infinite"
in your configuration. This doesn't really seem to work correctly, particularly for the case of NetTcp (It may work correctly for WSDualHttp Bindings, but I have never used those).
There are a number of other issues that are often associated with this: Including, Channel not faulting after client or server unexpectedly disconnected, Channel disconnecting after 10 minutes, Channel randomly disconnecting... Channel throwing exception when trying to open... Unable to configure Metadata on same endpoint...
Please note: There are two concepts that are important below. Infrastructure messages are internal to the way WCF communicates, and are used by the framework to keep things running smoothly. Operation messages are messages that occur because your app has done something, like send a message across the wire. Infrastructure messages are largely invisible to your app (but they still occur in the background) while operation messages are the result of an action your app has taken.
Information I have figured out, through hard won trial and error.
Infinite
does not appear to be a valid configuration setting in all situations (and certainly, the visual studio validation schema doesn't know about it).InfiniteIntConverter
and InfiniteTimeSpanConverter
which will sometimes work to convert the value Infinite
to either Int.MaxValue
or TimeSpan.MaxValue
, but I haven't yet figured out the situations in which this appears to be valid as sometimes it works, and sometimes it doesn't. What's more, it appears that some libraries will allow Infinite
in the config, while others will not, so you can succeed in one part of a configuration, but fail in another.inactivityTimeout
and receiveTimeout
, on both the client and the server. While these values do not HAVE to be the same, they probably should be as they will probably cause confusion if they are not. (technically, you can leave inactivityTimeout
to its default value if you want, but you should be aware of its value, and what it does)inactivityTimeout
should NEVER be set to a large value, much less Infinite
or TimeSpan.MaxValue
.inactivityTimeout
has two functions (and this is not widely understood). The first function defines the maximum amount of time that can elapse on a channel without receiving any "infrastructure" or "operation" messages. The second function defines the time period in which infrastructure messages are sent (half the time specified). If no infrastructure or operation messages have been received during the timeout period, the connection is aborted.receiveTimeout
specifies the maximum amount of time that can elapse between operation messages only. This value can be set to a large value, such as TimeSpan.MaxValue
(particularly if your channel runs internally over a trusted network or over a vpn). This value is what defines how long the reliable session will "stay alive" if there is no activity between client and server (other than infrastructure messages). ie, your client does not call any methods of the interface, and your server does not call back into the client. inactivityTimeout
and a large receiveTimeout
keeps your reliable session "tacked up" even when there is no operational activity between your client and server. The short inactivity timeout (i like to keep the default 10 minutes or less) sends infrastructure "ping" messages to keep the TCP connection alive while the long receive timeout keeps the reliable session active. while at the same time providing a reasonable timeout in case of disconnection.inactivityTimeout
to a large value, then the reliable session will not be reliable as it has no way to keep the Tcp connection alive, nor does it have any way to verify the integrity of the connection. It won't know if a user has disconnected unexpectedly until you try and send a message to that client and find out the connection is no longer there. This is why many people who use Infinite for this setting resort to creating a "Ping" method in their service, which is completely unnecessary if you've configured these settings correctly.inactivityTimeout
to a value larger than receiveTimeout
then it will likewise also be unreliable, as you will still be governed by the receiveTimeout
for operation messages. ie. if you forget to set receiveTimeout
and leave it at the default 10 minutes, then if the user is idle for 10 minutes, the connection will be aborted.ChannelFaulted
event handlers in various test situations, and sometimes the connection is faulted right away... other times it doesn't seem to fault at all. What i have discovered through trial and error is that the when it doesn't seem to fault, it will actually fault after the inactivityTimeout
expires on that end. (so if it's set to 10 minutes, then after 10 minutes it will call the ChannelFaulted
event). listenBacklog
and maxPendingConnections
on tcpTransport
, and groupName
and maxOutboundConnectionsPerEndpoint
on connectionPoolSettings
. True
. This uses a lot more overhead than turning it off. If you don't need ordered messages, i would suggest turning it off (need to set this on both sides)Configuration I still need to understand:
How do I correctly configure the shared net.tcp Metadata endpoint? (I will add an example when I get a chance) Currently, i'm specifying an http get url to bypass the problem. It's so inconsistent as to why it sometimes works and sometimes does not. I kept getting the error `The URI Prefix is not recognized' when generating the proxy in Visual Studio.
Why does WCF sometimes Fault the channel immediately upon disconnect, and sometimes waits for inactivityTimeout
to expire? What controls/causes one vs the other behavior?
Upvotes: 33
Views: 2622