How to fix “RedisConnectionException: No connection is available to service this operation” in Sitecore

Redis is a great choice for Sitecore’s shared session database. Sitecore has a good article which describes how to set this up, and links to this article to explain all options. I was running into issues when setting this up with my Azure Redis Cache which is using an access key. The “accessKey” attribute in the provider node was populated with the access key form the Azure portal. Initially i was seeing something like this in the log:

INFO  redisname.redis.cache.windows.net:6380,abortConnect=False
INFO
INFO  Connecting redisname.redis.cache.windows.net:6380/Interactive...
...
INFO  redisname.redis.cache.windows.net:6380 faulted: UnableToResolvePhysicalConnection on PING

Then the log would be full of errors like below:

ERROR GetItemFromSessionStore => StackExchange.Redis.RedisConnectionException: No connection is available to service this operation: EVAL
   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__DisplayClass12_0.b__0()
   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)

The only way I was able to get this to work was by not putting the access key in the provider but instead specifying it in the connection string (in ConnectionStrings.config):

<add name="sharedSession" connectionString="redisname.redis.cache.windows.net:6380,password=rediskey,ssl=True,abortConnect=False" />

Sitecore is now able to connect to Redis and all errors are gone from the log. Below lines from log file show the successful connect:

INFO  redisname.redis.cache.windows.net:6380,password=rediskey,ssl=True,abortConnect=False
INFO  Connecting redisname.redis.cache.windows.net:6380/Interactive...
....
INFO  Connect complete: redisname.redis.cache.windows.net:6380

Use Azure CDN Custom Origin for items in Sitecore media library

Using a CDN can significantly improve loading times of your site as static resources like images can be retrieved from it. A CDN has many edge servers and will automatically serve the resource from the closest location to the user. Additionally they will decrease the load on the webserver as it does not need to serve the resource to individual users.

Last year Azure announced custom origin support in their CDN. Before that you could only use the CDN from a limited set of Azure services in your Azure subscription like the Cloud Service that hosted your Sitecore environment. I have seen some complicated solutions to have the CDN use Sitecore. This was especially complicated if the cloud service hosted multiple Sitecore instances. Using the CDN is much easier with this new policy. This post will describe the steps involved in setting this up.

The first step is to set up the Azure CDN with custom origin, use the URL of your Sitecore site as the origin URL. This can be done either on the new or classic Azure Portal, see screenshots below:

custom-origin-new-portal
Classic portal:
custom-origin-blog

When the CDN is created it will generate a URL for it, something like http://az123456.vo.msecnd.net/ It is also possible to map a custom domain to this endpoint see here

Now the CDN is ready to use and you can retrieve any media library item, for example if your image has a URL of http://mysitecoresite.com/-/media/images/image.png then you can load it now from http://az123456.vo.msecnd.net/-/media/images/image.png

The CDN is now ready to use however the CDN edge servers will not cache the image but instead return it from the origin which is the Sitecore server. This is because by default Sitecore sets cache-control to private which causes the CDN not to cache it. This has to be changed to public in the Sitecore settings:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="MediaResponse.Cacheability">
        <patch:attribute name="value">public</patch:attribute>
      </setting>
    </settings>
  </sitecore>
</configuration>

Now static resources will be cached by Azure’s CDN edge servers so site will load faster for your users.

Avoid Sitecore performance degradation with SQL Azure

SQL Azure is a great choice for hosting Sitecore’s databases. Out of the box it provides many features like high uptime SLA, performance you can adjust easily based on demand and geo-replication. Since Sitecore 8 you can publish your databases to SQL Azure without any schema changes.

If you are using SQL Azure for a while you might notice that your Sitecore’s performance might go down over time especially at times when the database gets hit hard for example right after an application pool recycle. I initially had many incorrect assumptions regarding the source of these issues, I looked into prefetch cache, additional content, site traffic etc. Eventually i figured out that i had to update statistics and query plans which immediately resolved this issue.

This issue is not specifically related to Sitecore only but can be experienced with other technologies as well. However be sure to update statistics regularly to avoid any unnecessary performance issues in your site.