TT Lab
はじめる
学ぶ 学習パス コース

Tomcat & nginxの運用

アップストリームの負荷分散と障害隔離

TT Labで続きを見る

目標

nginxのアップストリームで複数のバックエンドに負荷を分散し、重み・セッション固定・障害の分離・Keep-Aliveを設定して、分散アルゴリズムを状況に合わせて選べるようになります。

なぜ重要なのか

SI現場でWASを2台以上置く理由は、性能よりも、1台が死んでもサービスが維持されるようにするためです。ところが、nginxオープンソース版にはアクティブヘルスチェックがないため、max_fails/fail_timeoutの意味を知らないと、「死んだサーバーにリクエストが行き続ける」状況を作ります。また、アップストリームのKeep-Aliveは、3つの設定がすべてあって初めて動作するのに、proxy_set_header Connection ""を書き忘れて、リクエストごとに新しいコネクションを作るシステムが、本当に多くあります。そうすると、TIME_WAITソケットが溜まり、ある瞬間にポートが枯渇します。

ステップ

  1. 準備: Tomcat(ポート8080)にlabhub.warをデプロイし、/opt/lab/samples/labhub-boot.jarをポート8082で起動しておきます。nginxは/root/ngをprefixとして使います。
  2. /root/ng/nginx.confにupstream appブロックを作って、127.0.0.1:8080と127.0.0.1:8082を入れ、ポート8088の/がこのグループにプロキシされるようにします。log_formatに$upstream_addrを必ず含め、アクセスログを/root/ng/logs/access.logに出力します。http://127.0.0.1:8088/versionが200である必要があります。
  3. リクエストを20回送ったあと、アクセスログを/root/ng/rr.logにコピーします。異なるアップストリームのアドレスが、2個以上記録される必要があります。
  4. 127.0.0.1:8080にweight=3を指定してreloadしたあと、アクセスログを空にしてリクエストを40回送り、/root/ng/weight.logにコピーします。ポート8080に行ったリクエストが、28–32回の間である必要があります。
  5. 分散方式をip_hashに変更してreloadしたあと、ログを空にしてリクエストを20回送り、/root/ng/iphash.logにコピーします。アップストリームのアドレスが1種類だけ記録される必要があります。
  6. ip_hashを削除して(設定ファイルに残っていてはいけません)、両方のサーバーにmax_fails=2 fail_timeout=10sを設定します。そのあとポート8082のプロセスを停止して、リクエストを10回送ります。10回とも200である必要があります。
  7. アップストリームのKeep-Aliveを設定します。upstreamブロックにkeepalive 32;を、locationにproxy_http_version 1.1;とproxy_set_header Connection "";を設定します。3つすべてがある必要があります。
  8. upstreamブロックにleast_conn;を追加して、文法チェックを通します。
  9. /root/ng/lb.mdを作成します。라운드로빈、가중치、ip_hash、least_connの4つの方式(韓国語の2つの語は、順に「ラウンドロビン」「重み」を意味します)について、それぞれいつ使うか、いつ使ってはいけないかを書きます。세션という単語(韓国語の語は「セッション」を意味します)が必ず登場する必要があり、全体で400文字以上である必要があります。

参考

アップストリームグループの構成

/root/ng/nginx.confにupstream appブロックを作って、127.0.0.1:8080と127.0.0.1:8082を入れ、ポート8088の/がこのグループにプロキシされるようにします。log_formatに$upstream_addrを必ず含め、アクセスログを/root/ng/logs/access.logに出力します。http://127.0.0.1:8088/versionが200である必要があります。

upstreamブロックはhttpコンテキストに置きます。proxy_passで、その名前をURLのように使います。2つのバックエンドを両方とも起動しておくことを、忘れないでください。

ラウンドロビンの分散の確認

リクエストを20回送ったあと、アクセスログを/root/ng/rr.logにコピーします。異なるアップストリームのアドレスが、2個以上記録される必要があります。

どのバックエンドに行ったかは、アクセスログのアップストリームアドレスの変数でわかります。リクエストを十分に送って、ログから固有のアドレス数を数えてみてください。

重み付けの分散

127.0.0.1:8080にweight=3を指定してreloadしたあと、アクセスログを空にしてリクエストを40回送り、/root/ng/weight.logにコピーします。ポート8080に行ったリクエストが、28–32回の間である必要があります。

nginxの重み付きラウンドロビンは、ランダムではなく決定的です。重みの比率が、そのまま分散の比率になります。

セッション固定

分散方式をip_hashに変更してreloadしたあと、ログを空にしてリクエストを20回送り、/root/ng/iphash.logにコピーします。アップストリームのアドレスが1種類だけ記録される必要があります。

同じクライアントを同じバックエンドに送る方式です。セッションをWASのメモリに置くレガシーシステムで、よく使われます。サーバーが追加・削除されると、再分配が起きるという欠点も、覚えておいてください。

障害サーバーの自動除外

ip_hashを削除して(設定ファイルに残っていてはいけません)、両方のサーバーにmax_fails=2 fail_timeout=10sを設定します。そのあとポート8082のプロセスを停止して、リクエストを10回送ります。10回とも200である必要があります。

nginxオープンソース版には、アクティブヘルスチェックがなく、失敗回数に基づくパッシブな方式だけがあります。バックエンドを1台実際に停止してみて、サービスが維持されるかを確認してください。

アップストリームのKeep-Alive

アップストリームのKeep-Aliveを設定します。upstreamブロックにkeepalive 32;を、locationにproxy_http_version 1.1;とproxy_set_header Connection "";を設定します。3つすべてがある必要があります。

3つを一緒に設定して初めて動作します。1つだけ欠けても、リクエストごとに新しいコネクションができます。特に、Connectionヘッダーをどう処理すべきかが、落とし穴です。

最小接続方式

upstreamブロックにleast_conn;を追加して、文法チェックを通します。

リクエストの処理時間のばらつきが大きいサービスで、ラウンドロビンよりも優れている理由を、考えてみてください。

分散アルゴリズムの選択基準の整理

/root/ng/lb.mdを作成します。라운드로빈、가중치、ip_hash、least_connの4つの方式(韓国語の2つの語は、順に「ラウンドロビン」「重み」を意味します)について、それぞれいつ使うか、いつ使ってはいけないかを書きます。세션という単語(韓国語の語は「セッション」を意味します)が必ず登場する必要があり、全体で400文字以上である必要があります。

各方式の長所だけを書いても、ドキュメントとは言えません。いつ使ってはいけないかも一緒に書いておけば、あとで判断に使えます。