Tuesday, November 29, 2011

A/B testing IIS sites on the same server using Application Request Routing (ARR)

I was recently asked to setup A/B testing for 2 sites on the same host.  This was for a Windows server running IIS.  I searched for some module or other quick way to get this done but couldn't find anything.  I found a bunch of posts talking about using Application Request Routing (ARR) to accomplish A/B testing but they required the use of 2 or more servers to act as members of the server farm.  I had only 1 host to work with and while I could have created another server or 2, I didn't want to have to manage another host and load balancer.


It took an hour of messing around and trying different setups but I was finally able to it setup.


The steps below show how to setup a single IIS server to allow is to host multiple sites for A/B testing using ARR and URL Rewriting.

Install Application Request Routing (ARR) 

The latest version of ARR (2.5) is available via Web PI.  From your server you can install from the Web App Gallery page or launch Web PI (Platform Installer) from within the IIS Manager Console.  There are a bunch of resources available for installing ARR and a quick Google search should get you pointed in the right direction.




Add some additional entries to the hosts file

ARR only allows 1 entry per host name in the server farm.  Since our hosts are all going to be served by localhost we need some additional "aliases" for localhost.  By creating additional hosts entries we can use these alternate names to all resolve to localhost (127.0.0.1).

Start Notepad.exe as an Administrator and open the file %windir%\System32\drivers\etc\hosts
Add 2 new entries that resolve to 127.0.0.1.

I used locala and localb.  Here is what my hosts file looked like when I was done.
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
# 127.0.0.1       localhost
# ::1             localhost
127.0.0.1 locala
127.0.0.1 localb
127.0.0.1 www.localab.com
127.0.0.1 localab.com

Setup A/B sites to listen on different ports
I'll include some steps here to create new sites.  You can modify your current site bindings accordingly.
The goal is to have the "A" site have a binding to hostname locala on port 9001 (or whatever port works best for you) and the "B" site with a binding to hostname localb on port 9002.  I also create a "shell" site that that holds the bindings for the url we are A/B testing.

mkdir %SystemDrive%\inetpub\wwwroot\site-a 
mkdir %SystemDrive%\inetpub\wwwroot\site-b
mkdir %SystemDrive%\inetpub\wwwroot\site-ab-shell
echo site-a > %SystemDrive%\inetpub\wwwroot\site-a\index.html
echo site-b > %SystemDrive%\inetpub\wwwroot\site-b\index.html
echo site-ab-shell > %SystemDrive%\inetpub\wwwroot\site-ab-shell\index.html
%systemroot%\system32\inetsrv\APPCMD add site /name:site-a ^
 /bindings:"http/*:9001:" /physicalPath:"%SystemDrive%\inetpub\wwwroot\site-a"
%systemroot%\system32\inetsrv\APPCMD add site /name:site-b ^
 /bindings:"http/*:9002:" /physicalPath:"%SystemDrive%\inetpub\wwwroot\site-b"
%systemroot%\system32\inetsrv\APPCMD add site /name:site-ab-shell ^
 /bindings:"http/www.localab.com:80:,http/localab.com:80:" ^
 /physicalPath:"%SystemDrive%\inetpub\wwwroot\site-ab-shell"

Configure ARR

Open up Internet Information Services (IIS) Manager
Right-click Server Farms and click Create Server Farm...
Name the farm ab (or whatever you want) and click Next
In the Server address: box enter locala (this is the hosts entry me made earlier)
Click Advanced settings...
Change httpPort to 9001 (this is the port we specified earlier when we created sites site-a)
Click Add

In the Server address: box enter localb (this is the hosts entry me made earlier)
Click Advanced settings...
Change httpPort to 9002 (this is the port we specified earlier when we created sites site-a)
Click Add
Click Finish


If you are presented with a Rewrite Rules popup click No. We will create the rule in the next step.





Setup Url Rewrite Rules

Open up Internet Information Services (IIS) Manager
Click on the root (parent) node on the left side Connections panel.  This URL Rewrite rule needs to be created at the root.

Double-click URL Rewrite
Click Add Rule(s)...
Select Blank rule and click OK
Name the rule A/B testing
In the Pattern: text box enter the text ".*" (without the double quotes)
Expand the Conditions group

Click Add...
In the Condition input: text box enter the text "{HTTP_HOST}"
In the Pattern: text box enter the text "(www\.|^)localab.com"
Click OK

Click Add...
In the Condition input: text box enter the text "{SERVER_PORT}"
Change the Check if input string: drop down to Does Not Match the Pattern
In the Pattern: text box enter the text "80"
Click OK


The {SERVER_PORT} rule is needed so that the traffic proxied by the load balancer does match.  Without this rule the proxied requests to locala or localb get stuck in an endless loop.




Expand the Action group
Change the Action type: to Route to Server Farm
Check the box Stop processing of subsequent rules
Click Apply on the right side actions pane


Setup ARR Load Balancing and Client Affinity

Open up Internet Information Services (IIS) Manager

Expand Server Farms and click the farm ab
Double-click Server Affinity
Check the box Client affinity
Click Apply
Click on the ab farm again
Double-click Load Balance
Change the Load balance algorithm: to Weighted round robin

Click Apply
If you see a popup for runtime statistics you can click Yes to reset the statistics

Test it out!

Going to http://localab.com should bring up a site that displays either "site-a" or "site-b".

If you see "site-ab-shell" then the URL Rewrite rule is not matching and the request is falling through to the shell site.  Double check the URL Rewrite rule.

You can close and open your browser and you should be balanced back and forth between sites.

You can view traffic stats for each site by going to Server Farms -> ab -> Monitoring and Management


1 comment:

  1. In "Setup Url Rewrite Rules", shouldn't the 2nd rule be "Matches the Pattern". We want only the client requests to be re-routed (i.e. with port 80) and not the server farm requests (ports 9001/9002), right?

    I had to make that small change to get it to work, but everything else is perfect. Thanks!!

    ReplyDelete