3

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?

Rob W.
  • 362
  • 5
  • 18

2 Answers2

1

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

Community
  • 1
  • 1
evasilchenko
  • 1,862
  • 1
  • 13
  • 26
  • I'll have to investigate this further, but externally restarting the service is not an option. The service is currently being hosted within a small exe (not IIS). – Rob W. Mar 13 '12 at 21:43
  • I don't know if it's not an option because you don't want to end all of the sessions but you can restart any service that's running within windows. http://www.csharp-examples.net/restart-windows-service/ – evasilchenko Mar 14 '12 at 16:42
  • Sorry, to clarify: Taking down the entire service to handle a corner case like this is not something I'm willing to do. The cost of regular interruption to the service is much higher than the possibility of this ever becoming a problem. – Rob W. Mar 16 '12 at 15:41
1

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.

Sixto Saez
  • 12,610
  • 5
  • 43
  • 51
  • I don't think it is configured for reliable messaging (notice the enabled="false"). If there's something else that I need to do to disable reliable messaging, I'm not aware of it. – Rob W. Mar 13 '12 at 21:41
  • Sorry about missing the `enabled="false"`, I focused in on the `ordered="true"` part. As a test, try disabling security as shown in this [forum post](http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/271b1816-173c-4c76-a4c4-fd9fda4b5e91) and also remove the reliableSession element from the config. See if that configuration helps with the orphaned sessions problem. If it does, re-able security and see if the problem comes back. If security is the cause then you'll need to decide whether disabling it is truly a solution or not for your situation. – Sixto Saez Mar 14 '12 at 16:53
  • If I get some spare time, I may try this just to see if it would help. Even if it does, unfortunately turning off security for this is not really an option. – Rob W. Mar 16 '12 at 15:43
  • WCF security in ws-* bindings is implemented, in part, using sessions as an optimization. That way authorization is only performed once per "session". It just occurred to me that another option may be to use basicHttpBinding over HTTPS using basic HTTP authentication. I don't believe basicHttpBinding uses sessions of any type and I'm pretty sure authentication performed on each request. It's worth a try and it does preserve encrypted authenticated access. – Sixto Saez Mar 16 '12 at 15:54