I've got a WCF service with the instance context mode set to PerCall, and using the wsHttpBinding. A poorly coded client has the ability to consume sessions without properly releasing them (ie the client doesn't call Close() on the client proxy). By looking at the "Percent of Max Concurrent Sessions" performance counter, I can see that each connection uses up a session, and doesn't release it. Under normal, well-behaved circumstances, the session is only used for a few moments while the results of the call are returned.
I've been trying to find a way to get these bad sessions to timeout and go away, but have been unsuccessful. Since it's not a reliable session, the RecieveTimeout and InactivityTimeout settings do not appear to have any effect. Here's a portion of my current config, which has a number of timeouts set in it, but does not seem to work:
<behaviors>
<serviceBehaviors>
<behavior name="UpdaterBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider"/>
<serviceCertificate findValue="xxxxxx" x509FindType="FindBySubjectName"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider"/>
<serviceThrottling maxConcurrentCalls="10" maxConcurrentSessions="10" maxConcurrentInstances="10" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="UpdaterBinding" messageEncoding="Mtom" maxReceivedMessageSize="100000000" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:01:00" sendTimeout="00:01:00">
<reliableSession ordered="true" inactivityTimeout="00:01:00"
enabled="false" />
<readerQuotas maxArrayLength="100000000"/>
<security>
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
I can set the serviceThrottling numbers much higher, but that just hides the problem for a while, and eventually a bad client would use all the sessions up. I want the server to free up any session that's been around for more than a few minutes, since there's no reason anything on this service should take that long.
Any suggestions?
Okay I may be totally off-base here but based on what I understood from your question, here is a possible solution:
Apparently you can get a list of active sessions but you can't terminate the session from the service side:
http://social.msdn.microsoft.com/Forums/en/wcf/thread/a6a72bd7-bd06-43e3-8abb-d6c10432a07b
One thing I can think of is if you're hosting the WCF service in IIS, you can create a windows service which is running on the server and looking at the active sessions. May be you can figure out when the session build up is unmanageable for the server and force it to restart the IIS application pool?
Restarting (Recycling) an Application Pool
One option to the orphaned sessions is to configure the wsHttpBinding to not use any features that depend on sessions (such as reliable messaging which is how the service is configured now).
If you have a business need that requires reliable messaging then go to the netMsmqBinding to get guaranteed message delivery but at the cost of designing around a one-way messaging pattern. DeviantSeev is correct that you cannot control the termination of sessions from the service but the solution he recommends is pretty drastic. It is not really feasible if you have a high volume environment like an eCommerce site because of the downtime caused by recycling the app pool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With