ロードバランサーを使用してトラフィックを分散するサーバーインスタンスのクラウドがAmazonで実行されています。現在、ブラウザ側で接続エラーを発生させることなく、ネットワークを適切に縮小するための良い方法を探しています。
私の知る限り、インスタンスの接続は、ロードバランサーから削除されると無礼に終了します。
インスタンスがシャットダウンする1分前のようにインスタンスに通知する方法、またはロードバランサーが停止中のインスタンスへのトラフィックの送信を停止するようにする方法が必要ですが、インスタンスへの既存の接続は終了しません。
私のアプリは、Ubuntuで実行されているnode.jsベースです。また、いくつかの特別なソフトウェアを実行しているので、node.jsホスティングを提供する多くのPAASを使用したくありません。
ヒントをありがとう。
このアイデアは、ELBの機能を使用して、異常なノードを検出し、プールから削除しますが、以下の仮定で期待されるように動作するELBに依存しています。これは私が自分でテストするつもりでしたが、まだ時間がありませんでした。答えが更新されたら更新します。
プロセスの概要
次のロジックは、ノードをシャットダウンする必要があるときにラップして実行できます。
アプリケーションに応じて「安全」であり、一部のアプリケーションでは判断できない場合があります。
テストが必要な仮定
ELB プールから異常なインスタンスを削除する これは正常であると期待しているので、次のようになります。
可能なテストケース:
1。 HTTP接続をブロックする方法
NodeXでローカルファイアウォールを使用して新しいセッションをブロックしますが、確立されたセッションは引き続き許可します。
例:IPテーブル:
iptables -A INPUT -j DROP -p tcp --syn --destination-port <web service port>
これは古い質問ですが、Amazonが最近connection draining
のサポートを追加したことに注意してください。つまり、インスタンスがロードバランサーから削除されると、インスタンスはインスタンスの前に進行中だったリクエストを完了します。ロードバランサーから削除されました。削除されたインスタンスに新しいリクエストがルーティングされることはありません。これらのリクエストにタイムアウトを指定することもできます。つまり、タイムアウトウィンドウより長く実行されたリクエストは、結局終了します。
この動作を有効にするには、ロードバランサーのInstances
タブに移動し、Connection Draining
の動作を変更します。
ELBからのトラフィックを分散するための推奨される方法は、複数のアベイラビリティーゾーンに同数のインスタンスを配置することです。例えば:
ELB
プログラムで(またはコントロールパネルを介して)インスタンスをデタッチできるようにする、2つの対象のELBAPIが提供されています。
ELB開発者ガイド には、アベイラビリティーゾーンを無効にした場合の影響について説明するセクションがあります。そのセクションの注記は特に興味深いものです。
ロードバランサーは常に、有効なすべてのアベイラビリティーゾーンにトラフィックを分散します。そのアベイラビリティーゾーンがロードバランサーに対して無効になる前に、アベイラビリティーゾーン内のすべてのインスタンスが登録解除または異常である場合、そのアベイラビリティーゾーンに送信されるすべてのリクエストは、DisableAvailabilityZonesForLoadBalancerがそのアベイラビリティーゾーンを呼び出すまで失敗します。
上記のメモで興味深いのは、DisableAvailabilityZonesForLoadBalancerを呼び出すと、ELBが利用可能なゾーンにのみリクエストの送信を即座に開始できることを意味する可能性があることです。無効なアベイラビリティーゾーンのサーバーでメンテナンスを実行している間、ダウンタイムが発生しない可能性があります。
上記の「理論」には、Amazonクラウドエンジニアによる詳細なテストまたは承認が必要です。
ここにはすでに多くの回答があり、そのうちのいくつかは良いアドバイスをしているようです。しかし、一般的にあなたのデザインには欠陥があると思います。シャットダウン手順をどのように完璧に設計しても、サーバーをシャットダウンする前にクライアント接続が閉じられていることを確認してください。
リストを続けることもできますが、私のポイントは、システムが常に正しく機能するように設計するのではなく、ということです。障害を処理するように設計します。サーバーの電力損失をいつでも処理できるシステムを設計すると、非常に堅牢なシステムが作成されます。これはELBの問題ではありません。これは、現在使用しているシステムアーキテクチャの問題です。
評判が悪い原因はコメントできません。これが私が作成したスニペットで、そこにいる誰かにとって非常に役立つかもしれません。これは、aws cliツールを利用して、インスタンスから接続が削除されたことを確認します。
ELBの背後に提供されたpythonサーバーを備えたec2-instanceが必要です。
from flask import Flask
import time
app = Flask(__name__)
@app.route("/")
def index():
return "ok\n"
@app.route("/wait/<int:secs>")
def wait(secs):
time.sleep(secs)
return str(secs) + "\n"
if __name__ == "__main__":
app.run(
Host='0.0.0.0',
debug=True)
次に、ローカルワークステーションからELBに向けて次のスクリプトを実行します。
#!/bin/bash
which jq >> /dev/null || {
echo "Get jq from http://stedolan.github.com/jq"
}
# Fill in following vars
lbname="ELBNAME"
lburl="http://ELBURL.REGION.elb.amazonaws.com/wait/30"
instanceid="i-XXXXXXX"
getState () {
aws elb describe-instance-health \
--load-balancer-name $lbname \
--instance $instanceid | jq '.InstanceStates[0].State' -r
}
register () {
aws elb register-instances-with-load-balancer \
--load-balancer-name $lbname \
--instance $instanceid | jq .
}
deregister () {
aws elb deregister-instances-from-load-balancer \
--load-balancer-name $lbname \
--instance $instanceid | jq .
}
waitUntil () {
echo -n "Wait until state is $1"
while [ "$(getState)" != "$1" ]; do
echo -n "."
sleep 1
done
echo
}
# Actual Dance
# Make sure instance is registered. Check latency until node is deregistered
if [ "$(getState)" == "OutOfService" ]; then
register >> /dev/null
fi
waitUntil "InService"
curl $lburl &
sleep 1
deregister >> /dev/null
waitUntil "OutOfService"
既存の回答で説明されていない警告は、ELBが60秒のTTLを持つDNSレコードを使用して、複数のELBノード(それぞれに1つ以上のインスタンスが接続されている)間の負荷を分散することです。
これは、2つの異なるアベイラビリティーゾーンにインスタンスがある場合、おそらくAレコードに60s TTLのELB用の2つのIPアドレスがあることを意味します。そのようなアベイラビリティーから最終インスタンスを削除すると、ゾーンでは、クライアントは少なくとも1分間は古いIPアドレスを使用する可能性があります。障害のあるDNSリゾルバーの動作はさらに悪化する可能性があります。
ELBが複数のIPを使用して同じ問題を抱えているもう1つの場合は、単一のアベイラビリティーゾーンに非常に多くのインスタンスがあり、1つのELBサーバーでは処理できない場合です。その場合、ELBは別のサーバーを作成し、そのIPを60秒のTTLでAレコードのリストに追加します。