Cara menggunakan Aplikasi ASP.NET dengan nol downtime

127

Untuk menggunakan versi baru situs web kami, kami melakukan hal berikut:

  1. Zip up kode baru, dan unggah ke server.
  2. Di server langsung, hapus semua kode langsung dari direktori situs web IIS.
  3. Ekstrak kode file zip baru ke direktori IIS yang sekarang kosong

Semua proses ini ditulis dalam skrip, dan terjadi dengan sangat cepat, tetapi masih ada downtime 10-20 detik ketika file lama dihapus, dan file baru sedang digunakan.

Adakah saran tentang metode downtime 0 detik?

Karl Glennon
sumber
Bukankah ini seharusnya ada di ServerFault?
Daniel Rodriguez
49
Mungkin, tetapi ServerFault tidak ada di Sep '08
Karl Glennon
3
Dapatkah IIS menunjuk ke folder symlink? Akankah mengubah symlink menyebabkan proses IIS untuk didaur ulang?
Neil McGuigan
ada solusi akhir dengan sampel skrip kode sumber lengkap?
Kiquenet
Apakah tidak mungkin memiliki beberapa kumpulan aplikasi dan mengalihkan lalu lintas dari satu kumpulan aplikasi ke yang lain?
Luke

Jawaban:

79

Anda membutuhkan 2 server dan penyeimbang beban. Berikut ini langkah-langkahnya:

  1. Hidupkan semua lalu lintas di Server 2
  2. Menyebarkan di Server 1
  3. Uji Server 1
  4. Nyalakan semua lalu lintas di Server 1
  5. Menyebarkan di Server 2
  6. Server Uji 2
  7. Hidupkan lalu lintas di kedua server

Masalahnya, bahkan dalam hal ini Anda masih akan memiliki aplikasi restart dan kehilangan sesi jika Anda menggunakan "sesi lengket". Jika Anda memiliki sesi database atau server negara, maka semuanya akan baik-baik saja.

Sklivvz
sumber
4
Anda juga dapat mengonfigurasi penyeimbang beban agar layanan sesi yang ada untuk server tertentu, tetapi tidak menerima yang baru. Itu memungkinkan Anda untuk menghindari sesi menjatuhkan. Namun teknik ini mengharuskan Anda menunggu sesi berakhir, dan secara umum Anda ingin membuat skrip ini.
35
Metode ini cenderung jatuh ketika gulungan kode memiliki perubahan struktural ke database. Setelah Anda memutakhirkan DB untuk Server 1, server 2 akan meledak. Sekarang Anda dapat membuat cadangan / memulihkan database untuk pengujian pada server 1, tetapi kemudian Anda memiliki masalah memilah data yang berubah dalam DB hidup saat sementara salinan paralel berjalan.
EBarr
1
@AndreiRinea - bagaimana menurut Anda ini akan bekerja dalam sistem OLTP volume tinggi? Entah sistem tidak sinkron dan Anda kehilangan data saat Anda memotong, atau Anda perlu menjeda entri data dan menulis skrip untuk mengidentifikasi & memigrasi data sementara ke struktur DB yang baru.
EBarr
9
@EBarr: dan dalam hal apa pun secara teknis Anda masih memiliki downtime nol pada aplikasi ASP.NET - pertanyaannya bukanlah "bagaimana cara menyebarkan ke server sql db dengan zero downtime".
Sklivvz
6
Mereka kuncinya adalah untuk mengembangkan dengan cara bahwa perubahan sql Anda tidak merusak. Anda sering harus melakukan perubahan sql yang merusak dalam rilis berikut setelah itu tidak lagi digunakan. Ini tidak sulit dilakukan dengan latihan.
Bealer
60

The Microsoft Web Deployment Alat mendukung ini untuk beberapa derajat:

Mengaktifkan dukungan Windows Transactional File System (TxF). Ketika dukungan TxF diaktifkan, operasi file bersifat atomik; yaitu, mereka berhasil atau gagal sepenuhnya. Ini memastikan integritas data dan mencegah data atau file dari yang ada di "setengah jalan" atau negara yang rusak. Di MS Deploy, TxF dinonaktifkan secara default.

Tampaknya transaksi ini untuk seluruh sinkronisasi. Selain itu, TxF adalah fitur Windows Server 2008, jadi fitur transaksi ini tidak akan berfungsi dengan versi sebelumnya.

Saya percaya mungkin untuk memodifikasi skrip Anda untuk downtime 0 menggunakan folder sebagai versi dan metabase IIS:

  • untuk jalur / url yang ada:
  • Salin situs web baru (atau modifikasi) ke server di bawah
    • \ web \ app \ v2.1 \
  • Ubah IIS metabase untuk mengubah jalur situs web
    • dari \ web \ app \ 2.0 \
    • ke \ web \ app \ v2.1 \

Metode ini menawarkan manfaat berikut:

  • Jika versi baru memiliki masalah, Anda dapat dengan mudah mengembalikan ke v2.0
  • Untuk menyebarkan ke beberapa server fisik atau virtual, Anda bisa menggunakan skrip Anda untuk penyebaran file. Setelah semua server memiliki versi baru, Anda dapat secara bersamaan mengubah metabase semua server menggunakan Microsoft Web Deployment Tool.
George Tsiokos
sumber
5
Saya telah menerapkan pendekatan ini dengan mengadaptasi skrip penyebaran PowerShell kami. Anda dapat melihat bagian skrip yang mengubah folder situs IIS di sini: stackoverflow.com/questions/330608/... Terima kasih atas penunjuknya.
Karl Glennon
17
Sayangnya, metode ini tidak memperhitungkan perubahan struktural pada DB. Setelah Anda memutakhirkan DB untuk v2.1 kemudian v.2.0 meledak.
EBarr
8
Menggunakan TxF berlebihan di sini, IMO. Tidak ada ruginya memiliki v2.0 dan v2.1 di sistem file secara bersamaan. Perubahan besar terjadi ketika v2.1 online, dan pada saat itu, transaksi TxF telah dilakukan. Downtime nol benar-benar terjadi karena cara IIS bergerak dari AppPool lama ke yang baru, bukan karena TxF.
RickNZ
5
Masalah lain dengan ini adalah jika sejumlah besar data pengguna disimpan dalam subfolder dari folder aplikasi.
Kenny Evitt
4
Ini bukan penyebaran 0 detik karena aplikasi baru perlu memulai.
usr
12

Anda dapat mencapai penerapan downtime nol pada server tunggal dengan memanfaatkan Penelusuran Permintaan Aplikasi di IIS sebagai penyeimbang beban perangkat lunak antara dua situs IIS lokal pada port yang berbeda. Ini dikenal sebagai strategi penyebaran biru hijau di mana hanya satu dari dua situs tersedia di penyeimbang beban pada waktu tertentu. Menyebarkan ke situs yang "turun", menghangatkannya, dan membawanya ke penyeimbang beban (biasanya dengan melewati pemeriksaan kesehatan Permintaan Aplikasi Routing), kemudian mengambil situs asli yang naik, keluar dari "kolam" (lagi dengan membuat pemeriksaan kesehatannya gagal).

Tutorial lengkap dapat ditemukan di sini.

kavun
sumber
7

Saya telah melalui ini baru-baru ini dan solusi saya datang dengan memiliki dua situs yang didirikan di IIS dan untuk beralih di antara mereka.

Untuk konfigurasi saya, saya memiliki direktori web untuk setiap situs A dan B seperti ini: c: \ Intranet \ Live A \ Interface c: \ Intranet \ Live B \ Interface

Di IIS, saya memiliki dua situs identik (port yang sama, otentikasi dll) masing-masing dengan kumpulan aplikasi mereka sendiri. Salah satu situs sedang berjalan (A) dan yang lainnya dihentikan (B). yang live juga memiliki header host langsung.

Ketika datang untuk menyebarkan untuk hidup, saya cukup mempublikasikan ke lokasi situs STOPPED. Karena saya dapat mengakses situs B menggunakan port-nya, saya dapat melakukan pra-pemanasan situs sehingga pengguna pertama tidak menyebabkan aplikasi mulai. Kemudian menggunakan file batch saya salin header host langsung ke B, berhenti A dan mulai B.

Rob King
sumber
1
Ini membantu dengan downtime karena menyalin file, tetapi memiliki masalah yang sama dengan @Sklivvz - segera setelah gulungan kode memiliki perubahan struktural ke database situs menjadi booming.
EBarr
Ini sepertinya merupakan cara intuitif bagi saya juga, tetapi mengapa tidak ada cara yang mudah dan terintegrasi untuk melakukan ini?
Petrus Theron
3
@Ebarr maka jangan meluncurkan perubahan sql yang merusak. Misalnya, jika Anda perlu menghapus kolom, lakukan di rilis berikutnya ketika tidak lagi digunakan oleh A atau B.
Bealer
@Bealer - setuju (dengan peringatan) .Ada serangkaian pertanyaan ini tentang "downtime selama peran kode". Saya belum menemukan satu yang benar-benar membahas realitas mengembangkan skema DB. Peringatan - ada berbagai komplikasi yang datang bersama dengan perubahan dua fase skema. Salah satu contoh - banyak ORM muntah jika definisi tabel berbeda dari definisi seperti yang dipahami (kolom baru atau tidak ada).
EBarr
2
@Rob, bagaimana Anda bisa "memanaskan dulu" situs itu jika dihentikan?
Andrew Gee
7

Menggunakan kelas ServerManager dari Microsoft.Web.Administration Anda dapat mengembangkan agen penempatan Anda sendiri.

Caranya adalah dengan mengubah PhysicalPath dari VirtualDirectory, yang menghasilkan pergantian atom online antara aplikasi web lama dan baru.

Ketahuilah bahwa ini dapat menghasilkan AppDomains lama dan baru yang dieksekusi secara paralel!

Masalahnya adalah bagaimana menyinkronkan perubahan ke database dll.

Dengan polling untuk keberadaan AppDomains dengan PhysicalPaths lama atau baru dimungkinkan untuk mendeteksi kapan AppDomain lama dihentikan, dan jika AppDomain baru telah dimulai.

Untuk memaksa AppDomain untuk memulai Anda harus membuat permintaan HTTP (IIS 7.5 mendukung fitur Autostart)

Sekarang Anda perlu cara untuk memblokir permintaan untuk AppDomain baru. Saya menggunakan mutex bernama - yang dibuat dan dimiliki oleh agen penempatan, menunggu oleh Application_Start dari aplikasi web baru, dan kemudian dirilis oleh agen penempatan setelah pembaruan database telah dibuat.

(Saya menggunakan file penanda di aplikasi web untuk mengaktifkan perilaku menunggu mutex) Setelah aplikasi web baru berjalan saya menghapus file penanda.

Mendongkrak
sumber
6

OK jadi karena semua orang downvoting jawaban yang saya tulis jauh di tahun 2008 * ...

Saya akan memberi tahu Anda bagaimana kami melakukannya sekarang pada tahun 2014. Kami tidak lagi menggunakan Situs Web karena kami menggunakan ASP.NET MVC sekarang.

Kami tentu tidak memerlukan penyeimbang beban dan dua server untuk melakukannya, tidak apa-apa jika Anda memiliki 3 server untuk setiap situs web yang Anda pelihara, tetapi itu adalah jumlah total yang harus dibayar untuk kebanyakan situs web.

Selain itu, kami tidak mengandalkan penyihir terbaru dari Microsoft - sihir yang terlalu lambat, dan terlalu banyak tersembunyi, dan terlalu rentan untuk mengubah namanya.

Inilah cara kami melakukannya:

  1. Kami memiliki langkah pembuatan pos yang menyalin DLL yang dihasilkan ke folder 'bin-pub'.

  2. Kami menggunakan Beyond Compare (yang luar biasa **) untuk memverifikasi dan menyinkronkan file yang diubah (melalui FTP karena didukung secara luas) hingga server produksi

  3. Kami memiliki URL aman di situs web yang berisi tombol yang menyalin semua yang ada di 'bin-pub' ke 'bin' (mengambil cadangan terlebih dahulu untuk mengaktifkan rollback cepat). Pada titik ini aplikasi restart sendiri. Kemudian ORM kami memeriksa apakah ada tabel atau kolom yang perlu ditambahkan dan membuatnya.

Itu hanya downtime milidetik. Restart aplikasi dapat memakan waktu satu atau dua detik tetapi selama permintaan restart buffered sehingga tidak ada downtime yang efektif.

Seluruh proses penyebaran memakan waktu mulai dari 5 detik hingga 30 menit, tergantung berapa banyak file yang diubah dan berapa banyak perubahan untuk ditinjau.

Dengan cara ini Anda tidak perlu menyalin seluruh situs web ke direktori yang berbeda tetapi hanya folder bin. Anda juga memiliki kontrol penuh atas proses dan tahu persis apa yang berubah.

** Kami selalu melakukan pengamatan cepat terhadap perubahan yang kami lakukan - sebagai pemeriksaan menit terakhir, jadi kami tahu apa yang harus diuji dan jika ada yang rusak, kami siap. Kami menggunakan Beyond Compare karena ini memungkinkan Anda dengan mudah membedakan file melalui FTP. Saya tidak akan pernah melakukan ini tanpa BC, Anda tidak tahu apa yang Anda timpa.

* Gulir ke bawah untuk melihatnya :( BTW Saya tidak akan lagi merekomendasikan Situs Web karena mereka lebih lambat untuk dibangun dan dapat rusak parah dengan setengah file temp yang dikompilasi. Kami menggunakannya di masa lalu karena mereka memungkinkan file-by-file lebih gesit penyebaran Sangat cepat untuk memperbaiki masalah kecil dan Anda dapat melihat apa yang Anda sebarkan (jika menggunakan Beyond Compare tentu saja - kalau tidak lupakan saja).

mike nelson
sumber
Namun, Anda masih akan mendapatkan waktu henti karena kumpulan aplikasi didaur ulang.
testpattern
Tidak, tidak ada downtime karena permintaan di-buffer secara otomatis oleh IIS selama restart aplikasi
mike nelson
5

Satu-satunya metode downtime nol yang bisa saya pikirkan melibatkan hosting di setidaknya 2 server.

Sam Meldrum
sumber
1

Saya akan sedikit memperbaiki jawaban George, sebagai berikut, untuk satu server:

  1. Gunakan Proyek Penerapan Web untuk melakukan pra-kompilasi situs menjadi DLL tunggal
  2. Zip up situs baru, dan unggah ke server
  3. Buka zip ke folder baru yang terletak di folder dengan izin yang tepat untuk situs, sehingga file yang tidak di-zip mewarisi izin dengan benar (mungkin e: \ web, dengan subfolder v20090901, v20090916, dll)
  4. Gunakan IIS Manager untuk mengubah nama folder yang berisi situs
  5. Simpan folder lama untuk sementara waktu, sehingga Anda dapat mundur jika terjadi masalah

Langkah 4 akan menyebabkan proses pekerja IIS untuk didaur ulang.

Ini hanya downtime nol jika Anda tidak menggunakan sesi InProc; gunakan mode SQL sebagai gantinya jika Anda dapat (bahkan lebih baik, hindari status sesi sepenuhnya).

Tentu saja, ini sedikit lebih terlibat ketika ada beberapa server dan / atau perubahan basis data ....

RickNZ
sumber
1
Masalah yang sama dengan @Sklivvz - Metode ini jatuh segera setelah gulungan kode memiliki perubahan struktural ke database.
EBarr
3
Itu sebabnya saya mengatakan itu lebih terlibat ketika ada perubahan DB ... Meluncurkan kode dengan perubahan struktural ke DB bukan hanya masalah penyebaran; juga harus ada dukungan dalam kode, dan mungkin juga dalam DB.
RickNZ
1

Untuk memperluas jawaban sklivvz, yang mengandalkan jenis penyeimbang beban (atau hanya salinan siaga di server yang sama)

  1. Arahkan semua lalu lintas ke Situs / Server 2
  2. Secara opsional, tunggu sebentar, untuk memastikan bahwa sesedikit mungkin pengguna memiliki alur kerja yang tertunda pada versi yang digunakan
  3. Menyebarkan ke Situs / Server 1 dan menghangatkannya sebanyak mungkin
  4. Laksanakan migrasi basis data secara transaksi (berusaha untuk memungkinkan ini)
  5. Langsung semua lalu lintas ke Situs / Server 1
  6. Menyebarkan ke Situs / Server 2
  7. Lalu lintas langsung ke kedua situs / server

Dimungkinkan untuk memperkenalkan sedikit pengujian asap, dengan membuat snapshot / salinan basis data, tetapi itu tidak selalu layak.

Jika mungkin dan perlu gunakan "perbedaan rute", seperti URL penyewa yang berbeda: s (customerX.myapp.net) atau pengguna yang berbeda, untuk disebarkan ke grup kelinci percobaan yang tidak diketahui terlebih dahulu. Jika tidak ada yang gagal, lepaskan untuk semua orang.

Karena migrasi basis data terlibat, memutar kembali ke versi sebelumnya seringkali tidak mungkin.

Ada beberapa cara untuk membuat aplikasi bermain lebih baik dalam skenario ini, seperti menggunakan antrian acara dan mekanisme pemutaran, tetapi karena kita berbicara tentang menyebarkan perubahan pada sesuatu yang sedang digunakan, benar-benar tidak ada cara pembodohan.

glilja
sumber
1

Beginilah cara saya melakukannya:

Persyaratan sistem minimum absolut:
1 server dengan

  • 1 load balancer / reverse proxy (mis. Nginx) berjalan pada port 80
  • 2 ASP.NET-Core / mono reverse-proxy / fastcgi chroot-jails atau docker-container mendengarkan pada 2 port TCP yang berbeda
    (atau bahkan hanya dua aplikasi reverse-proxy pada 2 port TCP yang berbeda tanpa kotak pasir apa pun)

Alur kerja:

mulai transaksi 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 
Stefan Steiger
sumber
-7

Saya sarankan menyimpan file-file lama di sana dan hanya menimpa mereka. Dengan cara itu downtime terbatas untuk menimpa file tunggal dan hanya ada satu file yang hilang pada suatu waktu.

Tidak yakin ini membantu dalam "aplikasi web" (saya pikir Anda mengatakan itu yang Anda gunakan), itulah sebabnya kami selalu menggunakan "situs web". Juga dengan penggunaan "situs web" tidak memulai kembali situs Anda dan membatalkan semua sesi pengguna.

mike nelson
sumber
Hai Mike, Anda mungkin ingin menghapus jawaban ini.
Sohail Ahmed