Memperbarui aplikasi web tanpa downtime


31

Ini adalah aplikasi PHP. Bagaimana saya bisa meminimalkan waktu henti saat memperbarui seluruh basis kode?

Jawaban:


44

Apa yang biasanya kita lakukan, di tempat kerja adalah:

  • sebelum kami memperbarui, akar dokumen server adalah:
    • di /www/app-2009-09-01
    • tetapi diakses melalui tautan simbolis, yang disebut /www/application
  • kami menempatkan seluruh basis kode baru /www/app-2009-09-08
  • setelah seluruh basis kode ada di sana:
    • kami menghapus tautan simbolis lama
    • kami membuat tautan simbolis baru, masih dipanggil /www/application, tetapi menunjuk ke sumber baru:/www/app-2009-09-08
  • kami memuat ulang apache untuk memaksa modifikasi diperhitungkan.

Semua proses ini dilakukan melalui skrip otomatis (satu-satunya hal yang tidak otomatis adalah kami meluncurkannya saat diperlukan). Ini berarti :

  • Semuanya berjalan cepat (terutama pergantian tautan simbolik, yang merupakan bagian penting)
  • Tidak ada risiko melakukan kesalahan: skrip telah diuji dengan baik, dan bekerja selama berbulan-bulan / tahun


Keuntungan lain dari pendahuluan tautan simbolis ini adalah sangat mudah untuk "mengembalikan" pembaruan jika kita melihat bug bencana hanya setelah menempatkan versi baru dari sumber ke produksi: kita hanya perlu mengganti tautan simbolis kembali.

Tentu saja, ini tidak mencegah Anda menguji versi baru di server pementasan Anda sebelum memproduksinya - tetapi, siapa yang tahu ... Kadang-kadang, ada bug yang sangat besar yang tidak ada yang bisa melihat sementara pengujian :-(
Misalnya, karena tidak ada pengujian beban yang dilakukan secara teratur pada mesin pementasan.
(Saya telah melihat "rollback" hal menggunakan sesuatu seperti 4 atau 5 kali dalam 3 tahun - setiap kali, itu menyelamatkan hari - dan situs web ^^)


Berikut adalah beberapa contoh cepat: misalkan saya memiliki VirtualHost ini dalam konfigurasi Apache saya:

<VirtualHost *>
        ServerName example.com
        DocumentRoot /www/application
        <Directory /www/application>
            # Whatever you might need here (this example is copy-pasted from a test server and test application ^^ )
            Options Indexes FollowSymLinks MultiViews +SymLinksIfOwnerMatch
            AllowOverride All
            php_value   error_reporting 6135
            php_value short_open_tag  on
        </Directory>
</VirtualHost>

Cukup "standar" ... Satu-satunya /www/applicationbukan direktori nyata: itu hanya tautan simbolis ke versi sumber saat ini.
Yang berarti ketika Anda telah meletakkan sumber ke server, tetapi belum beralih, Anda akan memiliki sesuatu seperti ini:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:08 application -> /www/app-2009-09-01

Perhatikan bahwa symlinc menunjuk ke "versi lama"

Sekarang, bahwa versi baru telah sepenuhnya diunggah ke server, mari beralih:

root@shark:/www
# rm /www/application
root@shark:/www
# ln -s /www/app-2009-09-08 /www/application

Dan, sekarang, /www/applicationpoin ke versi baru dari sumber:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:09 application -> /www/app-2009-09-08

Dan kita hanya perlu me-restart Apache:

root@shark:/www
# /etc/init.d/apache2 restart
 * Restarting web server apache2

Tiga langkah " hapus tautan; buat tautan baru; restart apache " harus dilakukan dengan cepat; yaitu, dengan skrip otomatis, dan bukan oleh manusia.

Menggunakan solusi ini:

  • Anda dapat meluangkan waktu sebanyak mungkin untuk mengunggah versi baru dari sumber: apache tidak akan menggunakannya selama simlik belum berubah
  • ketika semuanya OK, cukup ganti symlink: itu akan lebih cepat daripada mengubah bahkan 1 atau 2 file ... Yang berarti hampir tidak ada downtime :-)

Dan jika menggunakan beberapa opcode-cache seperti APC dengan opsi stat pada 0, itu bisa berarti risiko downtime lebih rendah, saya kira.


Tentu saja, ini adalah versi "sederhana" - jika Anda memiliki beberapa file yang diunggah, misalnya, Anda harus menggunakan symlink lain di suatu tempat, atau VirtualHost lain atau apa pun ...


Semoga ini lebih jelas :-)


Ini semacam pertukaran server juga. :-)
Wim ten Brink

mod_rewrite untuk mengelola tautan simbolik?

@gAMBOOKa: no: hanya masalah Apache DocumentRoot (atau VirtualHost DocumentRoot) Apache, yang merupakan / www / aplikasi ;; yaitu, tautan simbolik - di mana pun itu menunjuk.

2
Jawaban yang hebat. Namun, satu tip lagi: Anda dapat membuat tautan simbolik terjadi tanpa memutuskan tautannya. Seperti dikutip: "Tiga langkah ... harus dilakukan dengan cepat; yaitu dengan skrip otomatis, dan bukan oleh manusia." Perintah mv adalah operasi atom, sehingga Anda dapat membuat symlink seperti 'ln -s / www / app-2011-01-28 / www / application-temp' dan kemudian melakukan 'mv -T / www / application-temp / www / aplikasi '.

1
Ada sesuatu yang tidak dicakup oleh metode symlink. Cara Anda berfungsi dengan Apache + mod_php tetapi bisa gagal di lighttpd + fastcgi. Di situs web lalu lintas tinggi, permintaan akan dilayani di tengah bertukar tautan itu, ketergantungan kode php akan gagal dengan versi campuran.
Dennis C

2

Tidak bisakah Anda mengambil kode yang ada dan memigrasikan proyek ke file php pengujian terpisah, dan menggunakannya saat Anda membuat pembaruan? Yang saya maksud adalah, Anda harus memiliki server pengujian dan server produksi sehingga ketika Anda harus melakukan pembaruan, Anda tidak mengalami downtime.


1

Siapkan server kedua dengan basis kode yang diperbarui dan alihkan secepat mungkin. :-)

Jika tidak memungkinkan, pastikan basis kode Anda dibagi menjadi puluhan bagian yang lebih kecil. Maka waktu henti akan terbatas hanya pada satu sub bagian saja pada saat itu. Kode kunci yang lebih kecil lebih mudah untuk diganti dan sebagian besar hanya akan terus berjalan tanpa masalah. Coba saja ini di lingkungan uji dulu!


Karena aplikasi belum diuji dengan modul terfragmentasi, itu mungkin menghasilkan skenario yang tidak terduga.

Yang berarti bahwa ini akan menjadi daftar ToDo Anda setelah pembaruan ini. :-) Jadikan lebih modular dan Anda dapat memperbarui per modul.
Wim ten Brink

1
Itu ada di daftar ToDo, tetapi merupakan tujuan jangka panjang. Kami adalah startup muda, jadi organisasi di dalam tim dev akan memakan waktu cukup lama. = D

1

Pertama, saya sering menggunakan dan menyukai metode yang mirip dengan respons Pascal MARTIN.

Metode lain yang juga saya suka adalah menggunakan SCM saya untuk mendorong kode baru. Proses yang tepat tergantung pada jenis SCM Anda (git vs svn vs ...). Jika Anda menggunakan svn, saya ingin membuat cabang "online" atau "produksi" yang saya checkout sebagai root dokumen di server. Kemudian, setiap kali saya ingin mendorong kode baru dari cabang lain / tag / trunk, saya hanya memasukkan kode baru ke cabang "online" dan menjalankan pembaruan svn di root dokumen. Ini memungkinkan untuk pengembalian yang sangat mudah karena ada log revisi lengkap tentang apa yang naik / turun ke server dan siapa yang melakukannya dan kapan. Anda juga dapat dengan mudah menjalankan cabang "online" itu di kotak tes, memungkinkan Anda memeriksa aplikasi yang akan Anda tekan.

Prosesnya mirip dengan git dan gaya SCM lainnya, hanya dimodifikasi agar lebih alami untuk aliran kerja gaya mereka.

Ingin menarik / polling alih-alih mendorong pembaruan? Hanya memiliki pekerjaan cron atau lainnya, mekanisme yang lebih cerdas secara otomatis menjalankan pembaruan svn.

Ekstra: Anda juga dapat menggunakan proses ini untuk membuat cadangan file yang ditulis aplikasi Anda ke disk. Hanya memiliki pekerjaan cron atau mekanisme lain menjalankan svn commit. Sekarang file yang dibuat aplikasi Anda dicadangkan di SCM Anda, revisi dicatat, dll. (Mis., Jika pengguna memperbarui file pada disk, tetapi ingin Anda mengembalikannya, cukup tekan revisi lama).


0

Saya menggunakan pendekatan yang mirip dengan Pascal MARTIN juga. Tetapi alih-alih mengunggah beberapa versi aplikasi saya ke server produksi, saya menyimpan "build" di belakang firewall saya, masing-masing dalam direktori terpisah dengan nomor dan tanggal build. Ketika saya ingin mengunggah versi baru, saya menggunakan skrip sederhana yang menyertakan "rsync -avh --delay-updates". Bendera "tunda = pembaruan" akan mengunggah semuanya (yang berbeda) ke folder sementara sampai semua pembaruan ada, dan kemudian memindahkan semuanya sekaligus pada akhir transfer ke jalur yang semestinya sehingga aplikasi tidak akan pernah berada dalam negara setengah-setengah-baru. Ini memiliki efek yang sama dengan metode di atas, kecuali saya hanya menyimpan satu versi aplikasi di situs produksi (yang terbaik hanya memiliki file-file penting telanjang di server produksi, IMO).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.