はじめに

この実験では、HAProxyを使った負荷分散の基本を学びます。

窓口が 1 つしかない銀行を想像してください。行列が長くなり、利用者は不満を感じます。そこで銀行は複数の窓口を開設します。しかし今度は、入口で利用者を次に空いている窓口へ案内する担当者が必要になります。

この例では、次のように対応します。

  • 銀行の担当者が ロードバランサー(HAProxy) です。
  • 窓口担当者が バックエンドサーバー(シミュレーション用 Web サーバー)です。
  • 利用者が Web トラフィック です。

Linux 上にこの構成を作成します。2 台のシミュレーション用 Web サーバーを起動し、最も基本的な負荷分散アルゴリズムの 1 つである ラウンドロビン を使って、HAProxy が両方のサーバーにトラフィックを分散するよう設定します。

ラウンドロビンは、負荷分散の基本的な目的を理解するための出発点として役立ちます。正常なバックエンドが複数ある場合、すべてのリクエストを 1 台に送るのではなく、連続するリクエストを複数のバックエンドに順番に分散します。

この実験を終えると、次のことができるようになります。

  1. 簡単な Python Web サーバーを起動する。
  2. HAProxy がトラフィックを受け付けるフロントエンドと、サーバーへ転送するバックエンドを設定する。
  3. 負荷分散が実際に動作する様子を確認する。

ターミナルを準備する

ロードバランサーをテストするには、まず分散する対象が必要です。2 台の Web サーバーを同時に起動します。サーバーを起動すると、そのプロセスは停止するまでターミナルを占有するため、同じウィンドウで新しいコマンドを入力できません。

そのため、追加のターミナルタブを開きます。Web ブラウザーで複数のタブを開き、異なる Web サイトを同時に表示するのと同じイメージです。

このステップでは、システム内の役割を分けます。Python サーバーはアプリケーション層をシミュレートし、メインのターミナルはロードバランサー自体を操作する制御用の端末として使います。

現在、ターミナルが 1 つ開いています(Terminal)。次の手順で、さらに 2 つ開いてください。

  1. ターミナルの画面で **+**(プラス)アイコンを探します。
  2. そのアイコンを 2 回クリックして、Terminal 1 と Terminal 2 を開きます。

それぞれ次の用途で使います。

  • Terminal:HAProxy を設定する操作用ターミナル。
  • Terminal 1:Server 1 を起動するターミナル。
  • Terminal 2:Server 2 を起動するターミナル。

Server 1 を起動する

最初の「窓口」(Server 1)を起動します。高機能な Web サーバーソフトウェアをインストールする代わりに、Python に組み込まれている便利な機能を使って、任意のフォルダーを Web サイトとして公開します。

Terminal 1 に切り替えてください。

まず、Server 1 用に準備されたフォルダーへ移動します。

cd ~/project/server1

次に、サーバーを起動します。ポート 8001で待ち受けるように指定します。ポートはアパートの部屋番号のようなものです。コンピューターが建物で、ポート 8001 が Server 1 のある部屋です。

python3 -m http.server 8001

Serving HTTP on 0.0.0.0 port 8001 というメッセージが表示されます。これは、サーバーが起動し、アクセスを待機していることを示します。このターミナルは現在使用中のため、ここでは他のコマンドを入力しないでください。

Server 2 を起動する

次に、作業を分担できるように、2 つ目の「窓口」(Server 2)を起動します。

Terminal 2 に切り替えてください。

Server 2 用のフォルダーへ移動します。

cd ~/project/server2

このサーバーは別のポート、8002で起動します。Server 1 がすでに 8001 を使用しているため、8001 は使えません。2 つのサーバーを同じポート 8001 で起動することはできません。

python3 -m http.server 8002

これで、独立した Web サーバーが 2 台起動しました。一方はポート 8001 で「Response from Server 1」を返し、もう一方はポート 8002 で「Response from Server 2」を返します。

フロントエンドを設定する

サーバーの準備ができたので、「銀行の担当者」(HAProxy)がそれらへトラフィックを振り分けるように設定します。

ここからフロントエンドとバックエンドを分けて設定します。フロントエンドでは、クライアントが HAProxy へどのように接続するかを定義します。バックエンドでは、実際に処理を担当するサーバー群を定義します。

Terminal に戻ってください。

まず、既存の設定ファイルをバックアップして、新しい設定ファイルを作成します。

sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
sudo nano /etc/haproxy/haproxy.cfg

エディターに次の内容をコピーして貼り付けます。これは Frontend を定義します。Frontend はロードバランサーの公開窓口であり、利用者が接続する場所です。

global
    log /dev/log    local0
    log /dev/log    local1 notice
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend http_front
    bind *:80
    default_backend http_back

理解しておきたい主な部分:

  • bind *:80:HAProxy がポート 80で待ち受けるように指定します。ポート 80 は Web トラフィック(HTTP)で標準的に使われるポートです。ポートを指定せずに Web サイト名を入力すると、ブラウザーはポート 80 へ接続します。
  • default_backend http_back:ここへ接続してきた利用者のリクエストを、http_back という名前のサーバー群へ送るよう HAProxy に指示します。

この名前は重要です。HAProxy の設定は、基本的にトラフィックの経路図だからです。フロントエンドは接続を受け付け、バックエンドは接続先の候補を表します。

ファイルを保存します(Ctrl+O、Enter)。エディターを開いたままにしても構いませんが、進行状況を手順ごとに確認するには、保存して終了する(Ctrl+X)ことをおすすめします。

バックエンドを設定する

次に、処理を担当するサーバー群である Backend を定義します。

ファイルを閉じている場合は、もう一度開いてください。

sudo nano /etc/haproxy/haproxy.cfg

次の行をファイルの末尾に追加します。

backend http_back
    server server1 127.0.0.1:8001 check
    server server2 127.0.0.1:8002 check

ここで行ったこと

  • backend http_back:http_back という名前のサーバー群を作成しました。
  • server server1 ...:127.0.0.1:8001(localhost のポート 8001)にある最初のサーバー(Server 1)を登録しました。
  • server server2 ...:127.0.0.1:8002 にある 2 番目のサーバー(Server 2)を登録しました。
  • check:重要な指定です。担当者がサーバーの稼働状態(Healthy)を定期的に確認するよう指示します。サーバーが停止すると、HAProxy はそのサーバーへリクエストを送らなくなります。

ファイルを保存し(Ctrl+O、Enter)、終了します(Ctrl+X)。

負荷分散を確認する

担当者は、次の利用者をどのサーバーへ案内すればよいでしょうか。一般的な方法は ラウンドロビン です。単純に「順番に割り当てる」方式です。

  • 利用者 1 → Server 1
  • 利用者 2 → Server 2
  • 利用者 3 → Server 1
  • …このように続きます。

設定でこの方式を明示します。設定ファイルを最後にもう一度開きます。

sudo nano /etc/haproxy/haproxy.cfg

追加した backend http_back セクションを探し、balance ディレクティブを追加して、次のようにします。

backend http_back
    balance roundrobin
    server server1 127.0.0.1:8001 check
    server server2 127.0.0.1:8002 check

注:行頭のインデント(スペース)は読みやすさのために重要です。HAProxy は多少の違いを許容しますが、整った状態を保ってください。

ファイルを保存し(Ctrl+O、Enter)、終了します(Ctrl+X)。

HAProxy を再起動してテストする

設定ファイルの準備はできましたが、HAProxy はまだ変更内容を認識していません。変更を適用するため、サービスを再起動します。

sudo service haproxy restart

いよいよ動作を確認します。curl というコマンドを使います。curl は、グラフィカルな画面を持たない Web ブラウザーのようなものです。Web ページを取得し、そのテキストを画面に表示します。

localhost(このコンピューター自身)のデフォルトポート 80(HAProxy が待ち受けているポート)へ接続します。

次のコマンドを複数回実行してください。

curl localhost

Response from Server 1 と表示されます。もう一度実行します。

curl localhost

今度は Response from Server 2 と表示されます。

動作をすばやく確認するには、サーバーへ連続して 4 回アクセスする次のループコマンドを実行できます。

for i in {1..4}; do
  curl localhost
  echo
done

出力が 1、2、1、2 の順に正しく交互に表示されます。

これで、ロードバランサーが動作していることを確認できました。ポート 80 でリクエストを受け付け、ポート 8001 とポート 8002 の間で処理を公平に分散しています。

まとめ

この実験では、負荷分散された Web クラスターを構築しました。

実施した内容は次のとおりです。

  1. バックエンドのシミュレーション:Python を使い、異なるポート(8001、8002)で動作する 2 台の Web サーバーを作成しました。
  2. フロントエンドの設定:HAProxy が標準の Web ポート(80)で待ち受けるよう設定しました。
  3. バックエンドの設定:2 台のサーバーを処理担当のサーバー群として登録しました。
  4. ラウンドロビン:トラフィックを順番に分散する公平な方式を設定しました。

これは、大規模な Web サイトが数百万人の利用者に対応するために使っているものと同じアーキテクチャです。ただし、ここでは小規模な構成で実際に体験しました。