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


回答:


44

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

  • 更新する前のサーバーのドキュメントルートは次のとおりです。
    • /www/app-2009-09-01
    • と呼ばれるシンボリックリンクを介してアクセスされます /www/application
  • まったく新しいコードベースを /www/app-2009-09-08
  • コードベース全体がそこにあると:
    • 古いシンボリックリンクを削除します
    • まだ呼び出されている/www/applicationが、新しいソースを指す新しいシンボリックリンクを作成します。/www/app-2009-09-08
  • 変更を強制的に考慮するためにApacheをリロードします。

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

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


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

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


簡単な例を次に示します。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

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

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

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

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


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


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


それは一種のサーバー交換でもあります。:-)
ウィムテンブリンク

mod_rewriteでシンボリックリンクを管理しますか?

@gAMBOOKa:いいえ:ApacheのDocumentRoot(またはVirtualHost DocumentRoot)の問題です。これは/ www / applicationです;; すなわち、シンボリックリンク-それがどこを指しているかに関係なく。

2
素晴らしい答え。ただし、もう1つのヒント:リンクを解除せずにシンボリックリンクを作成できます。引用されているように:「3つのステップは…迅速に行われるべきです。すなわち、人間ではなく、自動化されたスクリプトによって。」mvコマンドはアトミック操作であるため、「ln -s / www / app-2011-01-28 / www / application-temp」などのシンボリックリンクを作成してから、「mv -T / www / application-temp / www / application '。

1
symlinkメソッドではカバーされなかったものがあります。あなたの方法はApache + mod_phpで動作しますが、lighttpd + fastcgiでは失敗する可能性があります。トラフィックの多いウェブサイトでは、リンクを入れ替える途中でリクエストが処理されますが、PHPコードの依存関係は混合バージョンでは失敗します。
デニスC

2

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


1

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

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


アプリは断片化されたモジュールでテストされていないため、予期しないシナリオが発生する可能性があります。

つまり、これはこの更新後のToDoリストに載ることになります。:-)よりモジュール化し、モジュールごとに更新できます。
ウィムテンブリンク

1
これはToDoリストに載っていますが、長期的な目標です。私たちは若い新興企業なので、開発チーム内の組織は自然に時間がかかります。= D

1

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

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

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

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

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


0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.