17

I'm not sure if this is the right way to ask this question, but here's basically what i'd like to do:

1.) Push a changeset to a site in IIS.
2.) Don't interrupt the users.
3.) Be able to roll back effortlessly.

So, there are a few things that I know have to happen:

1.) Out of Proc session - handled
2.) Out of Proc cache - handled

So the questions that remain:
1.) How do i keep from interrupting the users? If i just upload the files to bin, the app recycles and takes 10+ seconds to come back online
2.) How do i roll back effortlessly?

I was thinking a possible solution would be to have two sites set up in IIS, one public and one private. Uploads go to private and get warmed up. After warmup, the sites are swapped. A rollback only entails swapping to private without an upload.

This seems sound in theory, but Im not sure of the mechanics. Any ideas?

ChickenMilkBomb
  • 419
  • 6
  • 14
  • @NickatUship: is there just 1 server the website is hosted on? And if not, any possibility of adding a second? – MattB Mar 24 '10 at 14:35
  • @NickatUship: also, what IIS version are you on? – MattB Mar 24 '10 at 14:49
  • We could potentially solve this with our loadbalancer - thats true. I was hoping to be able to do something on the server itself - it would work better for our flow. We're on IIS 7. – ChickenMilkBomb Mar 24 '10 at 15:25
  • i wonder if we could use global URL rewrite rules for a zero downtime deploy 1)Rewrite *.domain.com to *.arbitrarysiteA.com which is an app in IIS 2.)upload to *.arbitrarySiteB.com 3.)warm it up 4.)switch the rewrite to *.siteB.com – ChickenMilkBomb Mar 24 '10 at 22:53

2 Answers2

29

Here is how I would approach this problem - keep in mind I haven't done this before, it is just concepts that I tested out a little bit in my dev environment. You should be able to setup a pretty robust framework using this and some scripting in your language of choice. Basically we are going to setup a ghetto load balancing environment and use that to switch between the new site and the old site.

To get it setup, you are going to need:

Install ARR to begin with.

Setup the 3 websites in IIS:

  • Website 1 will be the site your users actually connect to, lets say http://192.168.1.1/. This is also the ARR site. Just setup an empty directory for this to point to, and put it in its own app pool. Setup the app pool to not timeout according to these instructions.
  • Website 2 and 3 will be the sites that actually host your content. These need to be on their own IPs and due to how ARR works, on a different port than website 1. Lets say they are http://192.168.1.2:8080 and http://192.168.1.3:8080. They should also be in their own app pools, and point to different directories on the file system (but both directories have the same content typically)

After installing ARR, there will be a new category in IIS Manager called "Server Farms" - right click that and create a new farm.

  • give it a name that is meaningful to you
  • add Webserver 2 and Webserver 3 as the servers - make sure to click the "advanced settings" button, open up the "applicationRequestRouting" category and change the httpPort to 8080 for each server
  • Finish the wizard - you will be asked if you want to create URL Rewrite rules - click Yes
  • You now have a server farm - to finish the configuration, go to the farm and click the Proxy configuration button - turn on "reverse rewrite host in response headers" and apply the changes
  • In IIS Manager, go to the root level server category and click the URL Rewrite button, there will be a rule that was created for your farm
    • double click the rule to get to the settings
    • open the Conditions box
    • add a new condition for {SERVER_PORT} does not match 8080
    • apply the changes

At this point you have the basics of what we need to accomplish your request. If you go to http://192.168.1.1/ you will get your website from either Website 1 or Website 2, but it will be completely seamless that there are other sites.

Now what you can do when you want to deploy a new version of your application is:

  • drainstop 1 of the servers in your farm (in the server farm tools, go to "Monitoring and Management", choose a server and choose "Make server unavailable gracefully")
  • deploy your new version of the site to the system that is offline
  • warmup the site that is offline using its alternate IP/port
  • make the site available to the farm again
  • repeat the process for the other server

The Web Deployment tool comes into play when you talk about wanting to script all of this. It makes it super easy to create a package for your application and deploy it from the command line. You can also then rollback that package easily if there are problems. ARR is also scriptable using the Microsoft.Web.Administration dlls.

One other thing - if you are actually on Windows 2008 R2 (which is IIS 7.5) take a look at the Application Warmup module - it should make the warming up portion of this easier on you as well.

MattB
  • 11,194
  • 1
  • 30
  • 36
  • Awesome - thanks matt. +1 even just for putting this all down. I'll investigate and get back to the board. – ChickenMilkBomb Mar 25 '10 at 21:01
  • Perfect.. may not be fool proof.. but work investigating – Vivek Kumbhar Mar 25 '10 at 21:47
  • 1
    This is THE answer for zero downtime deploys of IIS applications. [I wrote an in depth tutorial on how to do this + automate it PowerShell.](https://kevinareed.com/2015/11/07/how-to-deploy-anything-in-iis-with-zero-downtime-on-a-single-server/) – kavun Nov 08 '15 at 06:12
10

MattB hit it out of the water. +1 I'll reply with more details but I'm not looking to take his points. I'll add to what he said.

I have a similar setup to what he described, and it works great. ARR is the way to go, even on a single server.

However, a couple things I would add.

Create the 2 sites, as Matt recommended. Call them something like yoursite.com01 and yoursite.com02.

Create 2 URL Rewrite rules. One for www.yourdomain.com and one more staging.yourdomain.com. For production, use {HTTP_HOST} with a value of (^www.yourdomain.com$)|(yourIP). (or whatever binding you prefer) For staging, use {HTTP_HOST} with a value of (^staging.yourdomain.com$). Call the rules yoursite.com and staging.yoursite.com.

Bind Rule=yoursite.com to site=yoursite.com01 and rule=staging.yoursite.com to site=yoursite.com02.

Setup FTP on staging.yoursite.com.

Production traffic is now going to Rule=staging.yoursite.com and Site=yoursite.com01. Stagging to the opposite.

You can deploy to staging at any point, test, pre-spinup, have other people test, etc. Do it during the day, it doesn't matter. Deploy to the same FTP account each time. Works great with build servers.

Then, when you're ready to go live, just make 3 changes: - move the FTP binding from yoursite.com02 to yoursite.com01 - change URL Rewrite Rule yoursite.com to point to yoursite.com02 - change URL Rewrite Rule staging.yoursite.com to point to yoursite.com01

Now you have Zero downtime, instant switching, with immediate roll-back functionality!

Your only gotcha to consider is your out of process session state. Make sure that your state server accepts both site ids so that you don't lose session state during the swap.

Also note that this is web only and not database.

For scripting, use Configuration Editor. Make the changes that you want and then click on "Generate Script". It will give you C#, appcmd or AHAdmin code.

I've had this in place for a few months with a webpage front end to swap instances and I'm never looking back. It makes deployments so refreshing compared to traditional deployments.

Scott Forsyth
  • 16,449
  • 3
  • 37
  • 56
  • @Scott - thanks for the followup, good to know what I posted isn't general craziness since I've never done it before. – MattB Mar 25 '10 at 21:37
  • I have not had much success making changes to URL Rewrite rules without incurring downtime. The majority of the time for me is: any changes to URL Rewrite rules on high traffic servers will spike CPU to 100% for ~5-10 seconds potentially causing timeouts and perceived slowness from users. – kavun Nov 08 '15 at 02:40
  • 1
    @kavun Yes, there is truth to that. At some version update in the last few years URL Rewrite rules at the global level started to cause appdomain recycles for all sites. That didn't used to be the case. So if you have ASP.NET sites on the same server then there could be an impact. However, if you have a dedicated ARR server just for this then the penalty for an appdomain recycle is minimal and you can still use a good solution like this. – Scott Forsyth Nov 18 '15 at 03:12