Implementation details
Sitecore relies on the default implementation of the ASP.NET SessionStateModule for session state management.
To avoid data collisions in the session store and unexpected session state behavior, the SessionStateModule and SessionStateStoreProviderBase classes include the functionality that exclusively locks the session store item for a particular session during the execution of an ASP.NET page.
If the SessionStateModule instance encounters locked session data during a call to either the GetItemExclusive or GetItem methods, it re-requests the session data at half-second intervals until either the lock has been released or the amount of time specified in the ExecutionTimeout property has elapsed.
This behavior is fully described in the Locking Session-Store Data MSDN article. You can obtain detailed information about the specific ASP.NET SessionStateModule behavior by providing the reference number 117091416336585 to Microsoft Support.
Excessive load nature
If multiple requests arrive with the same ASP.NET session identifier, each of them tries to obtain the exclusive lock for the session item, even though only one can succeed at a time. This causes an excessive load on the session state store produced by multiple threads that try to simultaneously lock the same unit.
You can observe the following symptoms when the session state store is under heavy load:
Message: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Source: System.Data
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
...
at System.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo, TimeSpan retryInterval)
Message: Unable to connect to SQL Server session database.
Source: System.Web
at System.Web.SessionState.SqlSessionStateStore.ThrowSqlConnectionException(SqlConnection conn, Exception e)
at System.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo, TimeSpan retryInterval)
...
at System.Web.SessionState.SessionStateModule.GetSessionStateItem()
at System.Web.SessionState.SessionStateModule.PollLockedSessionCallback(Object state)
Exception type: TimeoutException
Exception message: Timeout performing EVAL, inst: 14, mgr: Inactive, err: never, queue: 71, qu: 0, qs: 71, qc: 0, wr: 0, wq: 0, in: 65536, ar: 0, IOCP: (Busy=1,Free=999,Min=8,Max=1000), WORKER: (Busy=19,Free=32748,Min=8,Max=32767), clientName: RD0003FF85401C
at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
at StackExchange.Redis.RedisDatabase.ScriptEvaluate(String script, RedisKey[] keys, RedisValue[] values, CommandFlags flags)
at Sitecore.SessionProvider.Redis.StackExchangeClientConnection.<>c__DisplayClass7.<Eval>b__6()
at Sitecore.SessionProvider.Redis.StackExchangeClientConnection.RetryForScriptNotFound(Func`1 redisOperation)
at Sitecore.SessionProvider.Redis.StackExchangeClientConnection.RetryLogic(Func`1 redisOperation)
at Sitecore.SessionProvider.Redis.StackExchangeClientConnection.Eval(String script, String[] keyArgs, Object[] valueArgs)
at Sitecore.SessionProvider.Redis.RedisConnectionWrapper.TryTakeWriteLockAndGetData(String sessionId, DateTime lockTime, Object& lockId, ISessionStateItemCollection& data, Int32& sessionTimeout)
at Sitecore.SessionProvider.Redis.RedisSessionStateProvider.GetItemFromSessionStore(Boolean isWriteLockRequired, HttpContext context, String id, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actions)
at Sitecore.SessionProvider.Redis.RedisSessionStateProvider.GetItemExclusive(HttpContext context, String id, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actions)
at System.Web.SessionState.SessionStateModule.GetSessionStateItem()
ERROR Application error.
Exception: System.TimeoutException
Message: Timeout waiting for a MongoConnection.
Source: MongoDB.Driver
at MongoDB.Driver.Internal.MongoConnectionPool.AcquireConnection(AcquireConnectionOptions options)
...
at Sitecore.SessionProvider.MongoDB.MongoSessionStateProvider.GetItemExclusive(HttpContext context, String id, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actions)
at System.Web.SessionState.SessionStateModule.GetSessionStateItem()
at System.Web.SessionState.SessionStateModule.BeginAcquireState(Object source, EventArgs e, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
ERROR Application error.
Exception: MongoDB.Driver.MongoConnectionException
Message: Too many threads are already waiting for a connection.
Source: MongoDB.Driver
at MongoDB.Driver.Internal.MongoConnectionPool.AcquireConnection(AcquireConnectionOptions options)
at MongoDB.Driver.MongoServerInstance.AcquireConnection()
at MongoDB.Driver.MongoServer.AcquireConnection(ReadPreference readPreference)
at MongoDB.Driver.MongoCollection.Update(IMongoQuery query, IMongoUpdate update, MongoUpdateOptions options)
at Sitecore.SessionProvider.MongoDB.MongoSessionStateStore.InsertItem(String application, String id, Int32 flags, SessionStateStoreData sessionState)
at System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs)
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
ERROR Application error.
Exception: System.Web.HttpException
Message: The request queue limit of the session is exceeded.
Source: System.Web at System.Web.SessionState.SessionStateModule.QueueRef()
at System.Web.SessionState.SessionStateModule.PollLockedSession()
at System.Web.SessionState.SessionStateModule.GetSessionStateItem()
at System.Web.SessionState.SessionStateModule.BeginAcquireState(Object source, EventArgs e, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
To resolve this issue, consider the following options:
Increase the default polling interval for Sitecore Shared session state if Analytics tracking is enabled:
Note: This increases the waiting time between attempts to lock contact in the shared session state.
Configure the throttle concurrent requests per session and set a lower value than the default one (50):
Install .NET Framework 4.7 or higher on the server with Sitecore Content Delivery instance.
Note: To determine which .NET Framework versions are installed, see this article.<add key="aspnet:RequestQueueLimitPerSession" value="25"/>
<configuration>
...
<system.web>
...
<compilation targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
...
</system.web>
...
</configuration>
Switch the Private Session State to In-process mode and configure a Load Balancer to use sticky sessions: