Sunday, June 17, 2012

WCF on TCP : Keep your connections alive

I recently had a customer coming in with question and request on WCF connection pooling, which is very valid. I was almost convinced that answer to his question would be 'by design' but what worried me was if there is a solution for his predicament. To my pleasant surprise, mighty WCF team did think about the scenario and 'by design' there was a solution to his exact problem.

He is using net.tcp port sharing on the server for two different WCF services configured with net.tcp binding. The client code is such that proxy is created every time, service called and proxy closed. This sequence could be done for two services in any required combinations, lets say by calling Service 1() and Service2(). If Service1() is called repeatedly, TCP connection created in first call is pooled and reused. This is nice and as expected to save on connection establishment costs every time. But as soon as Service2() is called, TCP connection used for Service1() is reset. This sounds inappropriate. Seems, cost of port sharing is that pooled connection for Service1 has to be replaced with new connection to Service2. Very inefficient in an enterprise scenario where client makes random calls to Service1 and Service2 in volume as connection will be reset each time.

Whoever plays with TCP connection pooling is almost certain to stumble upon this: http://kennyw.com/work/indigo/173

Solution to my customer's predicament lies in this line taken from above link "Our connection pool is configurable through TcpConnectionPoolSettings/NamedPipeConnectionPoolSettings. These settings include a GroupName that we use for isolation"

You may think of it like this. TCP connection pool in WCF is identified with 'Port Number' and 'GroupName' (possibly more but only these are relevant for our purpose). If you omit 'GroupName', WCF provides a default. If you are not explicitly providing 'connectioPoolSettings', you are in effect omitting 'GroupName'. Since both the endpoints (for Service1 and Service2) use same port and have same 'GroupName' (Default), implies both endpoints will use same connection pool Id. When Service2 needs to be reached, its connection pool is already in place at client side but WCF infrastructure need to reset the connection to same port.

Use 'GroupName' to isolate connection pools for two endpoints and you can have connections alive when switching from Service1 to Service2 in there own respective pools.

This does mean that you will need to resort to custom binding but that’s an acceptable cost for such a huge benefit. A typical client config to achieve desired behaviour with net.tcp transport will look like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name = "bindingA">
          <tcpTransport>
            <connectionPoolSettings groupName="connectionPoolA"/>
          </tcpTransport>

Read more: DistributedWorld
QR: Inline image 1

Posted via email from Jasper-Net