Apache/php/mysqlを介してホスティングを提供する2つのISPがあります。私はそれらでdrupalを実行しています。時々mysqlサーバーが消える(クラッシュする)ので、サーバーA SQLがダウンした場合に、フェイルオーバーを行うための合理的な方法を見つけたいと思っていました。すべてのトラフィックはサーバーBに送信されます。
私は伝統的にこれが問題がある場合に2番目の代替IPが与えられるDNSで処理されることを知っています-または同様のもの。しかし、php、Perl、および通常のApacheのものを実行できることを除いて、私はispを制御できません。また、各ISPに静的IPがあり、DNSエントリ(A/CNAME/TXT)を作成できます。
だから、drupalに問題があるかどうかをチェックするスクリプトを作成する方法があるのではないかと期待していました。問題がある場合は、どういうわけかDNSを変更しますか?
または、他のアイデアはありますか? (より良いISPにもっと多くの$を費やす以外)
ラウンドロビンDNSは問題を解決しません-これはWebサーバーの負荷分散を提供するための優れた方法です-しかし、クライアントがポートに接続しようとして応答がない場合にフェイルオーバーが発生します(その後、次のDNSエントリを試行しますホストの場合)。明らかに、MySQLデータベースに障害が発生した場合、これはWebサーバーに直接影響を与えません(つまり、WebサーバーはTCP要求に応答します)。
原則として、PHPコードを取得して、データベースの障害を検出し、Webサーバーをシャットダウンするか、着信接続をブロックすることは可能ですが、これはかなり危険なアプローチです-ホスティングで許可されている場合でも発生する。
このシナリオに対処するために私が考えることができる唯一の実用的な方法は、障害が検出された場合に特定のホスト名にリダイレクトすることです。したがって、現在両方のホストをwww.example.comとして設定している場合は、www1のレコードを追加します。 .example.comとwww2.example.comの次に、自動追加インクルードファイルを追加して次のような操作を行います。
(on www1.example.com)
check_db();
// if check_db returns, then continue with normal processing...
function check_db() {
if (request is for www.example.com) { // avoid loops when both sites fail
if (last check more than 10 secs ago) {
if (database status bad) {
raise a database failed flag on the filesystem
redirect to www2.example.com
end
}
} else {
if (database failed flag set) {
redirect to www2.example.com
end
}
return OK
}
} else { // request is for www1.example.com i.e. we are already in failover mode
if (database failed flag set) && (last check more than 5 secs ago) {
if (database status good) {
remove database failed flag
return OK
} else { // oh no! both hosts down!
print sorry message and exit
}
} else if (last check more than 5 secs ago) {
if (database status bad) {
raise a database failed flag on the filesystem
print sorry message and exit
}
}
}
return OK
}
ただし、ブロッキング呼び出しを使用せずにデータベースが機能しているかどうかをテストする方法が必要です。
HTH
C。
負荷分散ではなく、フェイルオーバーを求めています。
フェイルオーバーは、特に同じインフラストラクチャ内にない機器では、うまく実行するのが非常に困難です。最良のケースは、ISPで冗長な地理的ロードバランサーを入手して、サイトをテストし、フェイルオーバーをシームレスに処理することです。予算が足りないと思うので、スティックとチューインガムの方法を選びましょう。
問題は明らかにWebサーバーではなくMySQLであるため、目前の問題を解決しましょう。
与えられた:
私が使用する方法は次のとおりです。
データベース接続の資格情報をディスクのどこかに(明らかにWebルート内ではなく)保存し、ページ接続ごとにロードします。次のようにsites/default /settings.phpを編集できます。
$ db_url = file_get_contents( '/ some/private/dir/drupal-db.url');
5秒(またはそれくらい)ごとにデータベースに接続し、マシンが読み取り可能な方法で障害をディスクに記録するバックグラウンドデーモンを作成します。 30秒(またはそれくらい)後に接続が失敗した後、ディスクに保存されている資格情報をバックアップサーバーの資格情報と「交換」します。これにより、Webサーバーは代替データベースサーバーからコンテンツを提供します。戻ってきた場合は、プロセスを逆にします。この場合、デバッグなどのためにロギングが不可欠です。
気を付けたい場合は、すべてのINSERTとUPDATEをWebサーバー上のディスクに記録して、フェイルオーバー後にデータベースを再同期できる可能性があります。ほとんどが「読み取り専用」の場合、これは必要ない場合があります。
ここでの主なポイントは、フェイルオーバーをWebアプリの操作から切り離すことです。よりモジュール化されており、Webアプリへの変更が簡単になります。
最後に、プライマリサーバーからバックアップデータベースに接続できることを確認します。これは、コマンドラインでgrantコマンドを使用して実行できます。
ホストBの場合:
mysql> GRANT ALL PRIVILEGES ON drupaldb.* TO username@'12.34.56.78' IDENTIFIED BY 'mypassword';
IPがホストAのものである場合。
そして、フラッシュすることを忘れないでください!
mysql> FLUSH PRIVILEGES:
次に、テストします。
bash> mysql -u username -pmypassword -h hostb drupaldb
まさか、インフラストラクチャを考えると、そのための適切なテクノロジーはありません。
DNSドメインのタイムアウトをSMALL(秒の範囲)にしないと、DNSは機能しません。それができれば、適切にスクリプトを作成できます(サーバー2のスクリプトはサーバー1に到達できないため、DNSエントリが変更されます)。それがほとんどそれを行う唯一の方法です。
DNSの設定に応じて、これは次のいずれかになります。OR-dyndns.orgなどを使用してホストエントリを登録し、INAエントリをCNAMEに置き換えます。DynDNS.orgにはHTTP経由で呼び出してエントリを変更できる優れたAPIであり、CNAMEは変更されません。また、ドメインを短いTTLに維持します。
それはほとんどすべてのオプションです。これらは他にもありますが、それらには、適切に配置されていない多くのインフラストラクチャが必要です。