Saturday, October 20, 2007

Mac Viewstate and Server Clusters / Web Gardens

The terms 'server farm' and 'web garden' may be foreign to many of us but they provide the mechanisms that allow us to cluster instances (web garden) or cluster servers (server farm). Server clusters specifically give us the following abilities:
 1. Have seperate Internet connections so that our sites can be load balanced. (For instance round-robin dns).
 2. Cluster of servers to either load balance client requests while providing the ability to pull one server out of the cluster for maintence or repair.
 3. Fault tolerance - if a server does go down then there are other servers that can handle the requests (if properly configured).

Web Gardens allow basically the same clustering on a single machine. You can set web gardens in the IIS MMC under Application Pools. See my notes at end of this article. In most cases, if you are not behind a proxy - this set-up works quite well as sticky-ip (sticky IP means that once your browser gets the first DNS record and can resolve the address and grab a page - it will always use that ip for consequent connections) seems to persist.

However, from a proxied connection - such as AOL, each request would randomly hit either the DSL hosted site or the cable hosted site. This causes problems because authentification can not occur. This is due to the fact that viewstate encryption keys are auto generated and as a result, the encryption from WEBSITE1 will be different than the viewstate encryption from WEBSITE2 and as a result WEBSITE1 can not decpiher the viewstate generated from WEBSITE2 and vice versa. You end up getting an error message like this:
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machinekey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Web.HttpException: Validation of viewstate MAC failed.

If this application is hosted by a Web Farm or cluster, ensure that <machinekey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster. Now, if you do a search on the web - the common solution is to add the following to your web.config:

<system.web>
<pages enableviewstatemac="false"></pages>
</system.web>

In my opinion - not the right thing to do as it is possible then for a visitor to hack your viewstate and possible data injections will be the result. Instead it is really simple to add the following under (Note key is only an example and will not work as is)

<system.web>
<machinekey decryptionkey="0B3757F0FA339A7933D601790BB5CA412B52E9F7EB899" validation="SHA1" validationkey="9133E0987FCA19C001E33F3B30FAD930B099F50712BF9BC9E1DA989F0DA2CD6CBF7">
</system.web>

Use this site to generate a key for you: http://www.aspnetresources.com/tools/keycreator.aspx Copy the key to your web config, and then copy that web.config to each website on each server in your cluster. (if you are using web gardens - then nothing additional is required as there are no multiple copies).

This is important because this 'static machineKey' will allow every server in your cluster or application instance in your web garden - to decrypt the viewstate regardless where which server or application instance generates the originating viewstate. It is recommended that a different machine key be used for each distinct website unless you intend on sharing user information across them. As long as this machine key is duplicated to the mirror sites on the other servers - you will be fine.
About 'web gardens', you can configure web gardens in the "Application Pools" snap-in of the IIS MMC. Web Gardens basically spawn a seperate instance of your application in its own dedicated thread. One reason you may want to do this is for fault tolerance. If one instance crashes - hopefully all remaining connections will be sent to the other instance until the crashed instance restarts. Performance wise - you will not get any gains from using web gardens. This has been my experience in load testing and stressing out sites with multiple web gardens. In some cases performance could suffer by using web gardens.

Hopefully this article will shed some light on how to scale your website in the scenarios listed. Fairly easy really and with the CSK - since there are no real complex session issues that really need to be considered, this should work for most people.