web-dev-qa-db-ja.com

ダウンタイムなしでWebアプリを更新する

それはPHPアプリです。コードベース全体を更新しながら、ダウンタイムを最小限に抑えるにはどうすればよいですか?

31
gAMBOOKa

仕事で一般的に行うことは次のとおりです。

  • 更新前のサーバーのドキュメントルートは:です
    • /www/app-2009-09-01
    • ただし、/www/applicationというシンボリックリンク経由でアクセスします
  • まったく新しいコードベースを/www/app-2009-09-08に配置します
  • コードベース全体がそこにあると:
    • 古いシンボリックリンクを削除します
    • /www/applicationと呼ばれる新しいシンボリックリンクを作成しますが、これは新しいソースを指します:/www/app-2009-09-08
  • apacheをリロードして、変更を考慮に入れます。

このプロセスはすべて、自動スクリプトを介して行われます(自動化されていないのは、必要なときに起動することだけです)。これの意味は :

  • すべてが高速になります(特に重要な部分であるシンボリックリンクの切り替え)
  • エラーを起こすリスクはありません:スクリプトは十分にテストされており、数か月/数年間動作します


このシンボリックリンクの手順のもう1つの利点は、新しいバージョンのソースを本番環境に配置した後でのみ壊滅的なバグに気付いた場合、更新を「ロールバック」するのが非常に簡単なことです。バック。

もちろん、これにより、ステージングサーバーで新しいバージョンをテストしてから実稼働に移行することを妨げることはありませんが、誰が知っているのか...時には、誰にも見られない大きなバグがありますテスト:-(
たとえば、ステージングマシンでは定期的に負荷テストが行​​われないためです。
(「ロールバック」というものが3年で4〜5回使用されるのを見てきました。そのたびに1日節約できました。ウェブサイト^^)


以下に、簡単な例を示します。Apache構成にこのVirtualHostがあるとします。

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

かなり「標準」...唯一のものは/www/applicationが実際のディレクトリではないことです。これはソースの現在のバージョンへの単なるシンボリックリンクです。
これは、ソースをサーバーに配置したが、まだ切り替えていない場合、次のようなものになることを意味します。

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

Symlincが「古いバージョン」を指すことに注意してください

新しいバージョンがサーバーに完全にアップロードされたので、切り替えましょう:

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

そして、今、/www/applicationはソースの新しいバージョンを指しています:

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

そして、Apacheを再起動するだけです。

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

3つの手順「リンクを削除し、新しいリンクを作成し、Apacheを再起動する」をすばやく行う必要があります。すなわち、自動化されたスクリプトによるものであり、人間によるものではありません。

このソリューションの使用:

  • ソースの新しいバージョンをアップロードするのに必要な時間をかけることができます:symlicが変更されていない限り、Apacheはそれらを使用しません
  • すべてが問題なければ、シンボリックリンクを切り替えるだけです。1つまたは2つのファイルを変更するよりも速くなります。つまり、実質的にダウンタイムはありません:-)

また、statオプションを0に設定してAPCのようなオペコードキャッシュを使用すると、ダウンタイムのリスクがさらに低くなる可能性があります。


もちろん、これは「シンプルな」バージョンです。たとえば、アップロードされたファイルがある場合は、どこか別のシンボリックリンク、または別のVirtualHostなどを使用する必要があります...


これがより明確であることを願って:-)

44
Pascal MARTIN

既存のコードを使用してプロジェクトを別のテストphpファイルに移行し、更新中にそれを使用することはできませんか?つまり、更新を行う必要があるときにダウンタイムが発生しないように、テストサーバーと運用サーバーを用意する必要があります。

2
THE DOCTOR

更新されたコードベースで2番目のサーバーをセットアップし、可能な限り高速に切り替えます。 :-)

不可能な場合は、コードベースが数十の小さな部分に分割されていることを確認してください。その場合、ダウンタイムは、一度に1つのサブパートのみに制限されます。小さいコードブロックは簡単に交換でき、ほとんどは問題なく実行され続けます。ただし、最初にテスト環境でこれを試してください!

1
Wim ten Brink

まず、Pascal MARTINの応答に似た方法をよく使います。

私が気に入っているもう1つの方法は、SCMを使用して新しいコードをプッシュすることです。正確なプロセスは、SCMのタイプ(git vs svn vs ...)によって異なります。 svnを使用している場合、サーバー上のドキュメントルートとしてチェックアウトする「オンライン」または「プロダクション」ブランチを作成するのが好きです。その後、別のブランチ/タグ/トランクから新しいコードをプッシュしたいときはいつでも、新しいコードを「オンライン」ブランチにコミットし、ドキュメントルートでsvn updateを実行します。これにより、サーバーにアップ/ダウンした内容と、だれが、いつ行ったかの完全なリビジョンログがあるため、非常に簡単にロールバックできます。また、テストボックスでその「オンライン」ブランチを簡単に実行して、プッシュしようとしているアプリを詳細に調べることができます。

このプロセスは、gitや他のスタイルのSCMでも同様ですが、ワークフローのスタイルに合わせてより自然になるように変更されています。

更新をプッシュする代わりにプル/ポーリングしたいですか? cronジョブまたは他のよりスマートなメカニズムでsvn updateを自動的に実行するだけです。

追加:このプロセスを使用して、アプリケーションがディスクに書き込んだファイルをバックアップすることもできます。 cronジョブまたは他のメカニズムにsvn commitを実行させるだけです。これで、アプリケーションが作成したファイルがSCMにバックアップされ、リビジョンが記録されます。(たとえば、ユーザーがディスク上のファイルを更新したが、元に戻したい場合は、古いリビジョンをプッシュするだけです)。

1
Sam Bisbee

Pascal MARTINにも同様のアプローチを使用します。しかし、アプリの複数のバージョンを運用サーバーにアップロードする代わりに、ファイアウォールの背後にある「ビルド」を、それぞれビルド番号と日付を持つ個別のディレクトリに保存します。新しいバージョンをアップロードする場合は、「rsync -avh --delay-updates」を含む簡単なスクリプトを使用します。 「delay = updates」フラグは、すべての更新が存在するまですべて(異なる)を一時フォルダーにアップロードし、転送の最後にすべてを一度に適切なパスに移動して、アプリが半分古い新しい状態。上記の方法と同じ効果がありますが、実稼働サイトにはアプリの1つのバージョンのみを保持します(実稼働サーバーで必要不可欠なファイルのみをIMOに配置するのが最善です)。

0
scotts