Architecture, Sitecore

Dedicated image server and Sitecore


A lot of sites which have a large amount of visitors use a dedicated image server.  There are several reasons for this, but mostly it is because that most browsers only allow a few simultaneous connections to the same domain, which stalls the download of a page that has more than two resources. For instance imagine you have a page consisting of multiple images, stylesheets and javascript files. As the clients only allows a few simultaneous downloads, the browser won’t download all the resources at the same time, but wait for each download to complete and first then start the next download.

The reason of this behavior is that the HTTP standard says that only two simultaneous connections between a client and a server should be allowed. This was specified to save servers from heavy IO load, when files where requested. Browsers like IE7 and Firefox 2 lives up to this standard and only allow 2 connections, while new browsers like IE8 and Firefox 3 allows 6 connections.
To ensure that the HTML can be fully loaded independently and without waiting for other downloads and to remove the load from the primary web server; a dedicated image server can be used. This server holds all files and uses a different domain (for instance images.mydomain.com). All files used on the page can then be fully referenced and thereby be downloaded from a different domain. Eg <img src=”http://images.mydomain.com/image1.jpg alt=”image1”/>. As the images are now on a different domain, these can be requested independently of the server providing the HTML and more simultaneous connections can be opened.

But how is this possible in Sitecore where the media library controls all the images?

One of the easiest ways is to have another publishing target for the media. In that way you will have two frontend servers: One serving the normal requests and one serving all media items. You can easily set up another publishing target and for instance use the staging module to clear the cache. Read more on SDN if you want to know how to set it up.

The remaining problem is: How do we ensure that all media items gets prefixed with another domain? Unfortunately there isn’t a simple setting for this (it will probably come in a future a release of Sitecore – I hope :)). However there is a simple solution to the problem as links are expanded by the LinkProvider, which can be overridden. More precisely the links are expanded in the LinkProvider.ExpandDynamicLink method, so we need to override this replacing the media path:

namespace TestApplication
{
  public class CustomLinkProvider : LinkProvider
  {
    public const string MEDIA_PATH = “~/media/”;

    public override string ExpandDynamicLinks(string text, bool resolveSites)
    {
      string baseExpands = base.ExpandDynamicLinks(text, resolveSites);
      return baseExpands.Replace(MEDIA_PATH, “http://images.pentia.dk/” + MEDIA_PATH);
    }
  }
}

Here I override the ExpandDynamicLinks in the inherited class CustomLinkProvider. I replace all media paths (identified by the prefix ~/media/) and replace it with the full path to the image server. The remaining thing to do is to replace the LinkProvider type in the web.config:

<linkManager defaultProvider=”sitecore”>
  <providers>
    <clear />
    <add name=”sitecore” type=”TestApplication.CustomLinkProvider, TestApplication” addAspxExtension=”true” alwaysIncludeServerUrl=”false” encodeNames=”true” languageEmbedding=”asNeeded” languageLocation=”filePath” shortenUrls=”true” useDisplayName=”false” />
  </providers>
</linkManager>

Here I just point the LinkProvider type to my own implementation.

Now that this is set up, all requests for media items will be handled by the image server. This does not just allow faster load times for the client, but will put less pressure on the main server. Further you can tune the media server to handling media items by increasing the media cache, setting the prefetch cache etc.

Enjoy your new Sitecore media server 🙂

Standard

12 thoughts on “Dedicated image server and Sitecore

  1. Nice work. Another alternative to multiple publishing targets is to have both mydomain.com and images.mydomain.com point to the same server using dns. That way, browsers will see the images as being hosted separately but only one live server is needed.

  2. Jens Mikkelsen says:

    Hi Adam,

    Yup. Thought about that as well, however you will not remove any load from the main webserver as it still serves the images. But if that isn’t a problem, your solution is more simple and easy to implement.

    Cheers

  3. Max S. says:

    Hi Jens,

    I implemented this and can trap the entering and executing of the ExpandDynamicLinks method when I attach to the w3wp.exe process, but it has no effect – the image still generates locally, whether I append my server name or even return an empty string.

    I followed all of the directions verbatim. Any idea what’s wrong?

    Thanks in advance.

  4. Jens Mikkelsen says:

    Hi Max,

    What version of Sitecore are you using? Do you have any other custom pipelines or something of the sort?

    Cheers
    Jens

    • Max S. says:

      6.1.
      Nothing custom.
      Alex Shyba tried this as well and told me that this works for rich text fields, but not for Image fields.

  5. Ahh, right you are! I only tested it for the rich text field.

    With out having tested it yet, I guess you’ll have to override the renderField processor GetImageFieldValue as well. I’ll try it out this weekend and update the post.

    Let me know if you get it to work.

    Cheers
    Jens

  6. Jens Mikkelsen says:

    Hi Max,

    I just tried it out. The problem is that the ExpandLinks processor is called just before the GetMediaField processor. Therefore it won’t expand the links correctly. You can switch the two processors around:

    Also you need to replacen /~/media in the imagefields, so the code for replacing the links should look like this instead:

    Regex regex = new Regex(“/?~/media/”);
    return regex.Replace(baseExpands, ImageUrl);

    Hope that makes sense… And sorry for the late reply 🙂

  7. Tom says:

    I have a similar setup, but I am having difficulties tuning the prefetch cache to be very minimal. SQL Profiler shows it is retrieving almost everything.

  8. Pingback: Dedicated image server in Sitecore – part 2 « Molten Core – a Sitecore blog

  9. Pingback: Dedicated image server in Sitecore – part 2 | cmsnewstoday.com

  10. Pingback: Storing Sitecore Media in the Database vs. the File System | Fire Breaks Ice

Leave a comment