views:

1973

answers:

7

To deploy a new version of our website we do the following:

  1. Zip up the new code, and upload it to the server.
  2. On the live server, delete all the live code from the IIS website directory.
  3. Extract the new code zipfile into the now empty IIS directory

This process is all scripted, and happens quite quickly, but there can still be a 10-20 second downtime when the old files are being deleted, and the new files being deployed.

Any suggestions on a 0 second downtime method?

+3  A: 

The only zero downtime methods I can think of involve hosting on at least 2 servers.

Sam Meldrum
+22  A: 

You need 2 servers and a load balancer. Here's in steps:

  1. Turn all traffic on Server 2
  2. Deploy on Server 1
  3. Test Server 1
  4. Turn all traffic on Server 1
  5. Deploy on Server 2
  6. Test Server 2
  7. Turn traffic on both servers

Thing is, even in this case you will still have application restarts and loss of sessions if you are using "sticky sessions". If you have database sessions or a state server, then everything should be fine.

Sklivvz
Two virtual machines would work too. :)
Till
You can also configure the load balancer so that it services existing sessions for a given server, but doesn't accept new ones. That allows you to avoid dropping sessions. This technique however requires waiting for the sessions to end, and in general you'll want to script this.
Willie Wheeler
This method tends to fall down when the code roll has structural changes to the database. Once you upgrade the DB for Server 1, server 2 will explode.Now you can backup/restore the database for testing on server 1, but then you have the issue of sorting out the data that changed in the live DB while while the parallel copy was running.
EBarr
+22  A: 

The Microsoft Web Deployment Tool supports this to some degree:

Enables Windows Transactional File System (TxF) support. When TxF support is enabled, file operations are atomic; that is, they either succeed or fail completely. This ensures data integrity and prevents data or files from existing in a "half-way" or corrupted state. In MS Deploy, TxF is disabled by default.

It seems the transaction is for the entire sync. Also, TxF is a feature of Windows Server 2008, so this transaction feature will not work with earlier versions.

I believe it's possible to modify your script for 0-downtime using folders as versions and the IIS metabase:

  • for an existing path/url:
  • Copy new (or modified) website to server under
    • \web\app\v2.1\
  • Modify IIS metabase to change the website path
    • from \web\app\2.0\
    • to \web\app\v2.1\

This method offers the following benefits:

  • In the event new version has a problem, you can easily rollback to v2.0
  • To deploy to multiple physical or virtual servers, you could use your script for file deployment. Once all servers have the new version, you can simultaneously change all servers' metabases using the Microsoft Web Deployment Tool.
George Tsiokos
I've implemented this approach by adapting our powershell deployment scripts. You can see the part of the script which changes the IIS site folder here:http://stackoverflow.com/questions/330608/changing-iis6-site-home-directory-with-powershell-answeredThanks for the pointer.
Recursieve
Unfortunately, this method doesn't account for structural changes to the DB. Once you upgrade the DB for v2.1 then v.2.0 explodes.
EBarr
Using TxF is overkill here, IMO. It doesn't hurt anything to have both v2.0 and v2.1 in the filesystem at the same time. The big change happens when v2.1 goes online, and by that time, the TxF transaction has been committed. The zero downtime really happens because of the way IIS moves from an old AppPool to a new one, not because of TxF.
RickNZ
A: 

If you do something like what GT said(I can't add a comment), you might lose session which would give a perceived restart. If you store session not inproc, you might get away with it, just the first few requests might be slow.

Other than switch around the folders, you could have two DNS names, server1.website.com and server2.website.com . Then set them up as two different websites, when you go to roll a new version, have server1 redirect to the same box, but to the other host name. You would have the web site installed twice, and would also need to store session out of proc and check your cookies. That should work though in theory.

Josh
You need to have session out of process given the question's statement. It has nothing to do with modifying the metabase.
George Tsiokos
A: 

I would suggest keeping the old files there and simply overwriting them. That way the downtime is limited to single-file overwrite times and there is only ever one file missing at a time.

Not sure this helps in a "web application" though (i think you are saying that's what you're using), which is why we always use "web sites". Also with "web sites" deploying doesn't restart your site and drop all the user sessions.

mike nelson
A: 

I would refine George's answer a bit, as follows, for a single server:

  1. Use a Web Deployment Project to pre-compile the site into a single DLL
  2. Zip up the new site, and upload it to the server
  3. Unzip it to a new folder located in a folder with the right permissions for the site, so the unzipped files inherit the permissions correctly (perhaps e:\web, with subfolders v20090901, v20090916, etc)
  4. Use IIS Manager to change the name of folder containing the site
  5. Keep the old folder around for a while, so you can fallback to it in the event of problems

Step 4 will cause the IIS worker process to recycle.

This is only zero downtime if you're not using InProc sessions; use SQL mode instead if you can (even better, avoid session state entirely).

Of course, it's a little more involved when there are multiple servers and/or database changes....

RickNZ
Same issue as @Sklivvz -- This method falls down as soon as the code roll has structural changes to the database.
EBarr
That's why I said it was more involved when there are DB changes... Rolling out code with structural changes to the DB is not just a deployment issue; there also has to be support in the code, and probably in the DB too.
RickNZ
+1  A: 

I went through this recently and the solution I came up with was to have two sites set up in IIS and to switch between them.

For my configuration, I had a web directory for each A and B site like this: c:\Intranet\Live A\Interface c:\Intranet\Live B\Interface

In IIS, I have two identical sites (same ports, authentication etc) each with their own application pool. One of the sites is running (A) and the other is stopped (B). the live one also has the live host header.

When it comes to deploy to live, I simply publish to the STOPPED site's location. Because I can access the B site using its port, I can pre-warm the site so the first user doesn't cause an application start. Then using a batch file I copy the live host header to B, stop A and start B.

Rob King
This helps with downtime due to file copy, but has the same issue as @Sklivvz -- as soon as the code roll has structural changes to the database the site goes boom.
EBarr