How to deploy an ASP.NET Application with zero downtime

后端 未结 11 1347
日久生厌
日久生厌 2020-11-28 00:38

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
相关标签:
11条回答
  • 2020-11-28 01:13

    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.

    0 讨论(0)
  • 2020-11-28 01:14

    This is how I do it:

    Absolute minimum system requirements:
    1 server with

    • 1 load balancer/reverse proxy (e.g. nginx) running on port 80
    • 2 ASP.NET-Core/mono reverse-proxy/fastcgi chroot-jails or docker-containers listening on 2 different TCP ports
      (or even just two reverse-proxy applications on 2 different TCP ports without any sandbox)

    Workflow:

    start transaction myupdate

    try
        Web-Service: Tell all applications on all web-servers to go into primary read-only mode 
        Application switch to primary read-only mode, and responds 
        Web sockets begin notifying all clients 
        Wait for all applications to respond
    
        wait (custom short interval)
    
        Web-Service: Tell all applications on all web-servers to go into secondary read-only mode 
        Application switch to secondary read-only mode (data-entry fuse)
        Updatedb - secondary read-only mode (switches database to read-only)
    
        Web-Service: Create backup of database 
        Web-Service: Restore backup to new database
        Web-Service: Update new database with new schema 
    
        Deploy new application to apt-repository 
        (for windows, you will have to write your own custom deployment web-service)
        ssh into every machine in array_of_new_webapps
        run apt-get update
        then either 
        apt-get dist-upgrade
        OR
        apt-get install <packagename>
        OR 
        apt-get install --only-upgrade <packagename>
        depending on what you need
        -- This deploys the new application to all new chroots (or servers/VMs)
    
        Test: Test new application under test.domain.xxx
        -- everything that fails should throw an exception here
        commit myupdate;
    
        Web-Service: Tell all applications to send web-socket request to reload the pages to all clients at time x (+/- random number)
        @client: notify of reload and that this causes loss of unsafed data, with option to abort 
    
        @ time x:  Switch load balancer from array_of_old_webapps to array_of_new_webapps 
        Decomission/Recycle array_of_old_webapps, etc.
    
    catch
            rollback myupdate 
            switch to read-write mode
            Web-Service: Tell all applications to send web-socket request to unblock read-only mode
    end try 
    
    0 讨论(0)
  • 2020-11-28 01:16

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

    0 讨论(0)
  • 2020-11-28 01:18

    To expand on sklivvz's answer, which relied on having some kind of load balancer (or just a standby copy on the same server)

    1. Direct all traffic to Site/Server 2
    2. Optionally wait a bit, to ensure that as few users as possible have pending workflows on the deployed version
    3. Deploy to Site/Server 1 and warm it up as much as possible
    4. Execute database migrations transactionally (strive to make this possible)
    5. Immediately direct all traffic to Site/Server 1
    6. Deploy to Site/Server 2
    7. Direct traffic to both sites/servers

    It is possible to introduce a bit of smoke testing, by creating a database snapshot/copy, but that's not always feasible.

    If possible and needed use "routing differences", such as different tenant URL:s (customerX.myapp.net) or different users, to deploy to an unknowing group of guinea pigs first. If nothing fails, release to everyone.

    Since database migrations are involved, rolling back to a previous version is often impossible.

    There are ways to make applications play nicer in these scenarios, such as using event queues and playback mechanisms, but since we're talking about deploying changes to something that is in use, there's really no fool proof way.

    0 讨论(0)
  • 2020-11-28 01:21

    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....

    0 讨论(0)
提交回复
热议问题