Iis – Two application pools or root virtual directories under one site

asp.netasp.net-mvcdeploymentiisiis-7

This might sound like a very dumb question, so let me first say what I want to achieve and then proceed to my question on how I'd envision something like this working.

I am trying to achieve completely seamless deploys of our web application to IIS (without interrupting users or active connections).

The way I envision this working is to have two root virtual directories sharing the same site. By root virtual directory I mean the one that IIS creates internally and assigns it to the root of each site or web application; except here I want to have two such root vdirs (each bound to their own app pool, but both referencing the exact same application from different folders). During normal operation, one of the vdirs would be inactive.

When doing a deployment, I would put the new code into another folder referenced by the second (inactive) vdir, and then mark it as active. What I want to accomplish is to then have IIS begin sending all new connections (requesting the same site) to that second vdir with the new code, but keeping the old one also alive & active until all remaining connections to it are dead (some, such as file uploads, could be long running). Once all of the lingering connections are dead, the old vdir/app pool becomes inactive and the second one with the new code becomes the only active one.

I hope this makes sense.

If it does not, here is my alternative attempt at explaining it with an example.

--- Web Site ("mysite.com")
    --- Root VDir#1 (IIS Internal, App Pool: AppPool#1, Virtual Path: /, Physical Path: C:\inetpub\MySite.v1084\). ACTIVE
    --- Root VDir#2 (IIS Internal, App Pool: AppPool#2, Virtual Path: /, Physical Path: NONE). INACTIVE

During a deployment, Root VDir#2 would become active and its Physical Path would change to C:\inetpub\MySite.v1085. That would be the default vdir IIS would serve for all new connections. Once all active sessions/connections to Root VDir#1 die, that becomes inactive.

Is something like this possible? Are there alternative ways of doing something like this (I know there is some form of built-in load balancing in IIS ("Web Farms"?) but am not too familiar with it).

Best Answer

What you are proposing sounds like an A/B swap. (Similar question)

There is an IIS addin tool from Microsoft called Web Deploy. It will automate most of the physical motions of deploying updated code into IIS but your requirement of seamless migration is the sticky point because you have long-running file-transactions. The best way to handle this is to get a load balancer, run with two production instances of your site at the same time and have a third instance for staging updates.

(BTW, Azure is doing something like this with "Cloud Services" -- there's a "Swap" command to do this exact thing.)

Going back to your particular setup, consider this configuration:

One IIS machine, two Web Sites. Web Site A and Web Site B. They do not point to the same files. They have their own folders. Web Site A is online and serving users in production, while Web Site B is offline. When you are ready to update, you update Web Site B, then swap On/Off Web Site A. Now B is online and A is offline. This is an A/B rotation. Later, when you do your next update, you update A, then swap On/Off with B. Now A is online and B is offline.

That exact moment, when you swap, there is the possibility of losing traffic -- (and you will probably kill those file transfers) but if your app is low volume, maybe no one will notice (you decide). However, if this is mission critical, high volume, site -- get a load balancer and use it as others have described.

What WebDeploy won't do, (as far as I know) is swap On/Off site A and site B. For that, you'll need to write a script and do it at the command line.

The benefit of the Web Deploy + scripts is that you can eventually automate this and maybe tie it into a continuous deployment system.

The long running file transfers are probably impossible to save with this setup. Another challenge is any in-memory state of your app. If your web app was designed with in-memory data, then you'll lose it when you do the A/B swap. If the programmers are using session, you may be able to turn on the session service. The session data will not be in the same process with the rest of the app and might survive the A/B swap. Talk to your programmers about how the app manages in-memory data. Maybe it doesn't actually have any. Maybe it can be easily recreated once the app reloads -- (e.g. rebuilding a cache from database)