Disabling ARR’s Instance Affinity in Windows Azure Web Sites
Setting up multiple instances of a website in Windows Azure Websites is a terrific way to scale out your website, and Azure makes great use of the Application Request Routing IIS Extension to distribute your connecting users between your active instances. ARR cleverly keeps track of connecting users by giving them a special cookie (known as an affinity cookie), which allows it to know, upon subsequent requests, to which server instance they were talking to. This way, we can be sure that once a client establishes a session with a specific server instance, it will keep talking to the same server as long as his session is active. This is of particular importance for session-sensitive application (a.k.a. stateless applications), because the session-specific data won’t move from one server to another on its own. Applications can be designed to do this (typically by storing that data in some kind of shared storage like SQL), but most are not and so normally, we want to keep every user attached to his designated server. If the user moves to another server, a new session is started, and whatever session data the application was using is gone (for example, the content of a shopping cart). Here’s a brief description of this process:
- Client connects to an Azure Web Sites website
- ARR runs on the front-end Azure server and receives the request
- ARR decides to which of the available instances the request should go
- ARR forwards the request to the selected server, crafts and attaches an ARRAffinity cookie to the request
- The response comes back to the client, holding the ARRAffinity cookie.
- When the client receives the request, it stores the cookie for later use (browsers are designed to do this for cookies they receive from servers)
- When the client submits a subsequent request, it includes the cookie in it
- When ARR receives the request, it sees the cookie, and decodes it.
- The decoded cookie holds the name of the instance that was used earlier, and so ARR forwards the request to the same instance, rather than choosing one from the pool
- The same thing (steps 7-9) repeat upon every subsequent request for the same site, until the user closes the browser, at which point the cookie is cleared
However, there are situations where keeping affinity is not desired. For example, some users don’t close their browser, and remain connected for extended periods of time. When this happens, the affinity cookie remains in the browser, and this keeps the user attached to his server for a period that could last hours, days or even more (in theory, indefinitely!). Keeping your computer on and browser open is not unusual, and many people (especially on their work-place computers) do it all the time. In the real world, this leads to the distribution of users per instance falling out of balance (that’s a little like how the line behind some registers in the supermarket can get hogged by a single customer, leading to others waiting in line more than they normally should).
Depending on your applications and what they do, you may care more or less about users being tied to to their servers. In case this is of little or no importance and you’d rather disable this affinity and opt for better load balancing, we have introduced the ability for you to control it.
Because the affinity is controlled by an affinity cookie, all you have to do to disable affinity is make sure that Azure doesn’t give the cookies out. If it doesn’t, subsequent requests by the user will be treated as “new”, and instead of trying to route them to “their” server, ARR will use its normal load-balancing behavior to route the request to the best server.
This is how the affinity cookie looks:
Disabling the affinity can be done in two ways:
- In your application
- In a site configuration
To control this behavior in an application, you need to write code to send out a special HTTP header, which will tell the Application Request Router to remove the affinity cookie. This header is Arr-Disable-Session-Affinity
, and if you set it to true, ARR will strip out the cookie. For example, you could add a line similar to this to your applications’ code:
* This example is for C#, but this could just as easily be done in any other language or platform.
Setting this in the application’s code would be suitable for situations you DO want affinity to be kept for the most part, and only reset on specific application pages. If, however, you prefer to have it completely disabled, you could have ARR remove the cookie always by having IIS itself inject that header directly. This is done with a customHeaders
configuration section in web.config
. Simply add the following into your web.config, and upload it to the root of the site:
Keep in mind, though, that the configuration in web.config
is sensitive, and a badly formatted file can stop the site from working properly. If you haven’t had a chance to work with web.config
files before, read this getting-started guide
If you intend on implementing this, you might wonder how to confirm its working and troubleshoot it. The ARR Affinity cookie is normally included with the 1st
response from any Azure Web Sites web site, and subsequently included with any request sent from the client and response received from the server. To see it in action, you could use any of multiple HTTP troubleshooting and diagnostic tools. Here is a list of some of the more popular options:
- Network Monitor
You can find info about several other tools here
. The 1st
one on the list, Fiddler, is one of the most popular, because it can interact with any browser, and is available for free. Once Fiddler is installed, it will record any URL you browse to, and you can then click on the Inspector tab for either the request or response to see the details. For example, below you can see the HTTP Headers tab, which show the affinity cookie sent by the server using the Set-Cookie header:
If you add the Arr-Disable-Session-Affinity
header to disable the affinity cookie, ARR will not set the cookie, but it will also remove the Arr-Disable-Session-Affinity
header itself, so if your process is working correctly, you will see neither. If you see both the cookie AND the header, this means that something is wrong with the way you set the header. Possibly an error in the text of the header name or its value. If you see the cookie and not the header, this probably means your changes to Web.config are invalid, or your header-injection code is not working, and you could try to confirm it by adding another, unrelated header. Generally speaking, it’s easier to set the headers with web.config than with code, so in case of doubt, you should start by simplifying it to reduce the surface area of your investigation.
In closing, we should mention that disabling the affinity is not something that should be taken lightly. For static content, it would rarely be an issue, but if you’re running applications, and they are not designed for dealing with users jumping from one server to another, it might not end well. For scenarios where the affinity has led to imbalance, this new ability will come as great news.