The recommended way to use DataCacheFactory in AppFabric

You may run into the following issues if you do not use the DataCacheFactory object in an appropriate way.

  • Many open TCP connections between the cache clients and the cache cluster
  • Socket errors as follows:

Exception type: System.InsufficientMemoryException
Message: Insufficient winsock resources available to complete socket connection initiation.
InnerException: System.Net.Sockets.SocketException
Stack:

Server stack trace:
   at System.ServiceModel.Channels.SocketConnectionInitiator.Connect(Uri uri, TimeSpan timeout)
   at System.ServiceModel.Channels.BufferedConnectionInitiator.Connect(Uri uri, TimeSpan timeout)
   at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
   at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   at Microsoft.ApplicationServer.Caching.CacheResolverChannel.Open(TimeSpan timeout)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
   at Microsoft.ApplicationServer.Caching.ChannelContainer.Opened(System.IAsyncResult)
   at System.Runtime.Remoting.Messaging.AsyncResult.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessageSink)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

The root cause is the cache client code creates a new DataCacheFactory object for each request on the fly but does not dispose it, which causes the machine running out of ports.

Though disposing a factory object will avoid the memory (ports) leak by releasing all associated resources, that is not the recommended way to use the factory object. Instead, you should keep a few (fixed count) of factory objects, and keep a handle to them. Creation and dispose of the factory objects is a relatively expensive operation. Cache factory objects own the underlying TCP channel between the client and servers, so you’d rather have it established once (or a few times if you have multiple cache client configurations to use) and keep using them for the lifetime of the process. For each DataCacheFactory instance, the maxConnectionsToServer attribute controls the number of TCP connections from the client to one cache server.

More info:
DataCacheFactory Members
Dispose: Closes the DataCacheFactory object and releases all associated resources.