読者です 読者をやめる 読者になる 読者になる

ELB の Connection Draining 機能を試した

AWS

Connection Draining とは

ELB には Connection Draining という機能がある.2014年3月に追加された機能で,現在新規に ELB を作成するとデフォルトで有効になっている(300秒).ただし,2014年3月時点で既に稼働していた ELB に関しては無効になっているため注意が必要.

簡単に表現すると,インスタンスを ELB から deregister したタイミングで実行中だったリクエストを切断せずに継続できる機能と言える.Connection Draining が無効になっていると,deregister したタイミングで切断されてしまう場合があって,デプロイなど ELB を操作するときにクライアントに 5xx が返ってしまう.

docs.aws.amazon.com

docs.aws.amazon.com

検証してみた

手元にあった PHP 環境で検証してみた.検証の内容を簡単に書くと,長めのリクエストを要求するのと同時に ELB から deregister して,レスポンスが返ってくるかどうかを確認した.スクリプトは PHP で60秒 sleep する感じで雑に書いた.

ちなみに,環境によって nginx や php-fpm あたりにリクエストのタイムアウト設定があって,そもそも返ってこないという場合がありえるため,そこは適宜変えてもらえれば.今回は php-fpm の request_terminate_timeout を長めに変更した.

<?php

set_time_limit(0);

echo "START\n";
echo "  sleep 60 second\n";
sleep(60);
echo "END\n";

Connection Draining 無効の場合

504 が返ってきた.Connection Draining が無効になっているため,deregister のタイミングで実行中だったリクエストが切断された.

$ curl http://example.com/sample.php --verbose
(中略)
< HTTP/1.1 504 GATEWAY_TIMEOUT
< Content-Length: 0
< Connection: keep-alive
<

Connection Draining 有効(300秒)の場合

ちゃんと60秒後にレスポンスが返ってきた.素晴らしい.

$ curl http://example.com/sample.php --verbose
(中略)
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Date: Wed, 18 May 2016 06:58:26 GMT
< Server: nginx
< Content-Length: 28
< Connection: keep-alive
<
START
  sleep 60 second
END

ちょっとした疑問

ドキュメントに書いてある通り,AWS CLI で Connection Draining を変更する場合は aws elb modify-load-balancer-attributes で実行できるけど,aws elb describe-load-balancers で確認することはできなかった.awscli に自分でパッチを当てると確認できるようになるらしいけど,そこまで頑張る気にならなくて諦めた.最新の AWS CLI 1.10.30 でも確認できなくて,ちょっと残念だ.

$ aws --version
aws-cli/1.10.30 Python/2.7.10 Darwin/15.4.0 botocore/1.4.20

まとめ

Connection Draining は ELB に register されたインスタンスに対する Graceful Stop 的な機能と言えるし,基本的には有効にしておくべきだと感じた.デフォルトの300秒に関しては,そのままでも良いし,アプリケーションのタイムアウト設定を考慮してもう少し減らしても良いとは思う.

関連記事