Some colleagues of mine are maintaining a large business application that uses the technology stack of classic ASP 3.0 and COM components written in Visual Basic 6. Changing the application itself to use more recent technology is not an option at the moment. Being a totally non-cutting-edge task, it turned out quite interesting in the end.
There’s one really problematic aspect in running this app: some features are quite hungry for memory. With a lot of concurrency going on, memory consumption has become the reason to add more servers to the server farm for some times now. Each of the servers is running a 32bit version of Windows Server, and is equipped with 4GB of RAM.
Now on a 32bit OS, the maximum amount of usable memory is 4GB in total, and half of that is reserved for the kernel. That makes 2GB left for all applications altogether.
IIS will not allocate all of this to applications. There is a memory limit that throttles the memory usage to 60% of what’s available (see here for more background, thanks Jason Follas) This percentage setting can be set in the
. Increasing this limit to 75% or 80% is doable on a dedicated web server (the key word is “dedicated” here. No additional services, please.)
Using the 4 gigabyte tuning (“/4GT”, formerly known as “/3G” boot switch), it is possible to let Windows use only 1GB for the OS kernel, and yield 3GB for applications. While this increases the memory available for the IIS worker processes, the OS becomes quite limited; running a load test after applying the setting is paramount (and I always found it scary).
These optimizations are good for some extra percent – but we were looking for a solution that would get the problem resolved for good. And that does not go without jumping the 4GB limitation on the server.
PAE looked promising, but with 64bit processors and operating systems well adopted, PAE looked like a bridging legacy technology, and moving to a 64bit environment a more forward-facing step.
Classic ASP on 64bit
There is no 64bit version of VB6, and there never will be. So if an ASP application needs to instantiate components written with VB6, it needs to run in a 32bit process. IIS 7 and IIS 7.5 support switching a worker process to 32bit on the Application Pool. This means that individual applications can be run as 32bit processes. But is that a good idea, compared to simply running on a 32bit operating system?
On a 64bit machine, there is of course a limit in how much memory can be assigned to a 32bit process that is imposed by the length of the address pointer, this limit is 4GB. But in contrast to the 32bit OS where this applies to the whole operating system, these 4GB are available to every process individually. So instead of 1.5 GB, there are 4 GB of memory available out of the box, without any advanced settings or modification.
Now to utilize the full amount of memory that a machine has to offer, you can run multiple of these processes. When a load balancing solution is already in place, you can simply replace the previously used physical machines by web sites on the same server, each with a different IP address. Each of the web site runs in a different application pool, in its own 32bit process. Each of these processes manages its own 4GB of memory. As IIS does not allocate all of this memory, it’s safe to run four web sites on a server with 16GB of RAM.
Application Request Routing as local load balancer
If no existing load balancer is in place, IIS Application Request Routing (“ARR”) can be used to distribute requests between the web sites on the server locally. With this model, the web sites that run the ASP applications are bound against local IP addresses: in addition to the external IP address on a physical network adapter, a loopback adapter is installed. A range of private IP addresses (like 192.168.42.x/255.255.255.0) is assigned to the loopback adapter. In addition to the web sites for the ASP application, there needs to be one web site that is bound against the external IP address. This web site should point to an empty directory so that there is no interference between resources available on that web site, and URLs that are handled by the application web sites.
In the configuration of ARR, a web farm addresses each of the web sites on the server as an individual server. ARR creates a default routing rule that routes all incoming requests to the web farm that consists of the local web sites. There is a problem with this rule however: because the application web sites are local, ARR will recognize requests coming into these sites too. This creates a closed loop. ARR needs to ignore requests that come into the local web sites: a condition is added to the default routing rule that it only kicks in when the server IP address is not within the local network address range used for the application web sites.
If the classic ASP session is used, clients need to be sent to the same web site every time; the ASP session is stored in the context of the worker process. This is achieved by activating Client Affinity in ARR – ARR sets a cookie itself, and uses this cookie to determine the web site to send clients to.