[編集者– この投稿はもともと 2016 年に公開されましたが、それ以降に改訂された NGINX 機能を使用するように更新されました。 詳細については、 「NGINX JavaScript モジュールとNGINX Plus ダッシュボードを使用した高度なログ記録」を参照してください。
NGINX Plus R5で TCP ロード バランシングを導入し、その後のリリースでも継続的に機能を追加し、 UDP ロード バランシングもサポートしています。 この記事では、TCP ロード バランシングの主な要件と、NGINX Plus がそれらにどのように対応するかについて説明します。
NGINX Plus の機能を調べるために、拡張されたデータベース バックエンドを持つアプリケーションの主要コンポーネントを表すシンプルなテスト環境を使用します。 テスト環境の構築に関する詳細な手順については、付録を参照してください。
この環境では、NGINX Plus はデータベース サーバーのリバース プロキシとして機能し、デフォルトの MySQL ポート 3306 をリッスンします。 これにより、クライアントにシンプルなインターフェースが提供され、バックエンドの MySQL ノードは、クライアントに何ら影響を与えることなくスケールアウト (さらにはオフラインに) できます。 テスト環境のフロントエンド アプリケーションを表すクライアントとして、 MySQL コマンドライン ツールを使用します。
この記事で説明されている機能の多くは、NGINX Open Source と NGINX Plus の両方に適用されます。 簡潔にするために、全体を通じて NGINX Plus を参照し、NGINX Open Source では利用できない機能を明示的に示します。
以下のユースケースを検討します。
アプリケーションの負荷分散を構成する前に、アプリケーションがデータベースに接続する方法を理解することが重要です。 ほとんどのテストでは、MySQL コマンドライン ツールのmysql(1)
を使用して Galera クラスターに接続し、クエリを実行してから接続を閉じます。 ただし、多くのアプリケーション フレームワークでは、待ち時間を最小限に抑え、データベース サーバーのリソースを効率的に使用するために接続プールを使用します。
TCP 負荷分散はストリーム
構成コンテキストで構成されているため、メインのnginx.confファイルにストリーム
ブロックを追加して、基本的な MySQL 負荷分散構成を作成します。
これにより、TCP 負荷分散構成がメイン構成ファイルから分離されます。 次に、 nginx.confと同じディレクトリにstream.conf を作成します。 デフォルトでは、 conf.dディレクトリはhttp
構成コンテキスト用に予約されているため、そのディレクトリにストリーム
構成ファイルを追加しても機能しないことに注意してください。
まず、Galera クラスター内の 3 つの MySQL ノードを含むgalera_clusterという名前のアップストリーム
グループを定義します。 私たちのテスト環境では、それぞれ固有のポート番号を使用してローカルホスト上でアクセスできます。 ゾーン
ディレクティブは、負荷分散状態を維持するためにすべての NGINX Plus ワーカー プロセス間で共有されるメモリの量を定義します。 server{}
ブロックは、NGINX Plus がクライアントを処理する方法を構成します。 NGINX Plus はデフォルトの MySQL ポート 3306 をリッスンし、すべてのトラフィックをアップストリーム
ブロックで定義された Galera クラスターに転送します。
この基本構成が機能していることをテストするには、MySQL クライアントを使用して、接続した Galera クラスター内のノードのホスト名を返します。
$ echo "変数名 = 'ホスト名' の変数を表示" | mysql --protocol=tcp --user=nginx --password=plus -N 2> /dev/nullホスト名 node1
負荷分散が機能していることを確認するには、同じコマンドを繰り返します。
$ !!;!!!;!!ホスト名 node2 ホスト名 node3 ホスト名 node1
これは、デフォルトのラウンドロビン負荷分散アルゴリズムが正しく動作していることを示しています。 ただし、アプリケーションが接続プールを使用してデータベースにアクセスする場合 (上記のように)、ラウンドロビン方式でクラスターへの接続を開くと、各ノードで接続数が不均衡になる可能性があります。 さらに、接続はアイドル状態(アプリケーションからのクエリを待機中)であったり、クエリの処理でビジー状態であったりする可能性があるため、接続を特定のワークロードと同一視することはできません。 長時間持続する TCP 接続に適した負荷分散アルゴリズムは、 least_conn
ディレクティブで設定されるLeast Connectionsです。
これで、クライアントがデータベースへの新しい接続を開くと、NGINX Plus は現在の接続数が最も少ないクラスター ノードを選択します。
クラスター全体でデータベースのワークロードを共有する大きな利点は、高可用性も実現できることです。 上記の設定では、NGINX Plus は新しい TCP 接続を確立できない場合にサーバーを「ダウン」としてマークし、そのサーバーへの TCP パケットの送信を停止します。
このようにダウンしたサーバーを処理することに加えて、NGINX Plus は、クライアントのリクエストが送信される前に使用できないサーバーが検出されるように、自動でプロアクティブなヘルス チェックを実行するように構成することもできます (これは NGINX Plus のみの機能です)。 さらに、アプリケーションのヘルスチェックでサーバーの可用性をテストできます。つまり、各サーバーにリクエストを送信し、正常であることを示す応答が得られるかどうかを確認できます。 これにより、構成が次のように拡張されます。
この例では、 match
ブロックは、 MySQL プロトコル バージョン 10 ハンドシェイクを開始するために必要な要求データと応答データを定義します。 server{}
ブロックのhealth_check
ディレクティブはこのパターンを適用し、NGINX Plus が実際に新しい接続を受け入れることができるサーバーにのみ MySQL 接続を転送することを保証します。 この場合、20 秒ごとにヘルス チェックを実行し、1 回の失敗後に TCP ロード バランシング プールからサーバーを除外し、2 回連続してヘルス チェックが成功した後にそのサーバーへのロード バランシングを再開します。
NGINX Plus は柔軟なログ記録機能を備えているため、すべての TCP/UDP 処理を記録してデバッグやオフライン分析を行うことができます。 MySQL などの TCP プロトコルの場合、NGINX Plus は接続が閉じられたときにログ エントリを書き込みます。 log_format
ディレクティブは、ログに表示される値を定義します。 Stream モジュールで使用可能な任意の変数を選択できます。 ログ形式は、 stream.confファイルの先頭にあるストリーム
コンテキストで定義します。
ログ記録を有効にするには、 server{}
ブロックにaccess_log
ディレクティブを追加し、ログ ファイルへのパスと、前のスニペットで定義したログ形式の名前を指定します。
これにより、以下のサンプルのようなログ エントリが生成されます。
$ tail -3 /var/log/nginx/galera_access.log 192.168.91.1 [23/Jul/2021:17:42:18 +0100] TCP 200 369 1611 127.0.0.1:33063 0.000 0.003 12.614 12.614 192.168.91.1 [23/Jul/2021:17:42:18 +0100] TCP 200 369 8337 127.0.0.1:33061 0.001 0.001 11.181 11.181 192.168.91.1 [23/Jul/2021:17:42:19 +0100] TCP 200 369 1611 127.0.0.1:33062 0.001 0.001 10.460 10.460
NGINX JavaScript は、「NGINX ネイティブ」のプログラム構成言語です。 これは、サーバー側のユースケースとリクエストごとの処理向けに特別に設計された、NGINX および NGINX Plus 用の独自の JavaScript 実装です。
[編集者注– 以下の使用例は、NGINX JavaScript モジュールの多くの使用例の 1 つにすぎません。 すべてのユースケースのリストについては、 「NGINX JavaScript モジュールのユースケース」を参照してください。
この投稿は、 NGINX JavaScript 0.2.4で導入された Stream モジュールのリファクタリングされたセッション オブジェクトと、 NGINX
JavaScript 0.4.0で導入されたjs_import
ディレクティブを使用するように更新されました。
TCP/UDP ロード バランシング用の Stream モジュール内では、NGINX JavaScript によって要求パケットと応答パケットの内容にアクセスできるようになります。 つまり、SQL クエリに対応するクライアント要求を調べて、 SELECT
やUPDATE
などの SQL メソッドなどの有用な要素を抽出できるということです。 NGINX JavaScript は、そのような値を通常の NGINX 変数として使用できるようにします。 この例では、JavaScript コードを/etc/nginx/sql_method.jsに配置します。
getSqlMethod()
関数には、現在のパケットを表す JavaScript オブジェクト ( s
) が渡されます。 このオブジェクトのfromUpstream
やbuffer
などのプロパティは、パケットとそのコンテキストに関する必要な情報を提供します。
アップストリーム MySQL サーバーから送信されるパケットを調べる必要はないため、最初に TCP パケットがクライアントから送信されているかどうかを確認します。 ここで、最初の 2 つのパケットにはハンドシェイクと認証情報が含まれているため、3 番目のクライアント パケットに注目します。 3 番目のクライアント パケットには SQL クエリが含まれます。 この文字列の先頭は、メソッド
配列で定義された SQL メソッドの 1 つと比較されます。 一致が見つかったら、結果をグローバル変数$method
に保存し、エラー ログにエントリを書き込みます。 NGINX JavaScript ログは、重大度情報
でエラー ログに書き込まれるため、デフォルトでは表示されません。
同じ名前の NGINX 変数が評価されるときに、 setSqlMethod()
関数が呼び出されます。 この場合、変数には、 getSqlMethod()
関数の呼び出しから取得された NGINX JavaScript グローバル変数$method
が設定されます。
この NGINX JavaScript コードは、単一のクエリが実行される MySQL コマンドライン クライアント用に設計されていることに注意してください。 コードはそれらのユースケースに合わせて調整できますが、複雑なクエリや長時間の接続を介した複数のクエリを正確にキャプチャすることはできません。 NGINX JavaScript モジュールをインストールして有効にする手順については、 NGINX Plus 管理者ガイドを参照してください。
ログに SQL メソッドを含めるには、 log_format
ディレクティブに$sql_method
変数を含めます。
また、NGINX JavaScript コードをいつどのように実行するかを NGINX Plus に指示するために、設定を拡張する必要もあります。
まず、 js_import
ディレクティブを使用して NGINX JavaScript コードの場所を指定し、 js_set
ディレクティブを使用して、 $sql_method
変数を評価する必要があるときに NGINX Plus にsetSqlMethod()
関数を呼び出すように指示します。 次に、 server{}
ブロック内で、 js_filter
ディレクティブを使用して、パケットが処理されるたびに呼び出される関数を指定します。 オプションで、 info
オプションを指定したerror_log
ディレクティブを追加して、NGINX JavaScript ログを有効にすることもできます。
この追加構成を適用すると、アクセス ログは次のようになります。
$ tail -3 /var/log/nginx/galera_access.log 192.168.91.1 [23/Jul/2021:17:42:18 +0100] TCP 200 369 1611 127.0.0.1:33063 0.000 0.003 12.614 12.614 更新 192.168.91.1 [23/Jul/2021:17:42:18 +0100] TCP 200 369 8337 127.0.0.1:33061 0.001 0.001 11.181 11.181 選択 192.168.91.1 [2021年7月23日:17:42:19 +0100] TCP 200 369 1611 127.0.0.1:33062 0.001 0.001 10.460 10.460 更新
[編集者– このセクションは、NGINX Plus APIを参照するように更新されました。NGINX Plus API は、ここで最初に説明した個別の拡張 Status モジュールを置き換え、廃止します。 ]
MySQL アクティビティを詳細にログに記録するだけでなく、NGINX Plus ライブ アクティビティ監視ダッシュボードで、リアルタイムのメトリックとアップストリーム MySQL サーバーの健全性を観察できます (NGINX Open Source は、より少ないメトリック セットをStub Status APIを通じてのみ提供します)。
NGINX Plus ダッシュボードはNGINX Plus R7で導入され、 NGINX Plus APIへの Web インターフェースを提供します。これを有効にするには、別の/etc/nginx/conf.d/dashboard.confファイルのhttp
コンテキストに新しいserver{}
ブロックを追加します。
MySQL サービスの監視データを収集できるようにするには、 stream.confのserver{}
ブロックをstatus_zone
ディレクティブで更新する必要もあります。
この設定を行うと、NGINX Plus ダッシュボードはポート 8080 で利用できるようになります。 次のスクリーンショットでは、3 つの MySQL サーバーが表示されており、それぞれに多数の進行中の接続の詳細と現在のヘルス ステータスが表示されています。 ポート 33062 でリッスンしているノードでは、以前に 18.97 秒間の短い停止が 1 回発生していたことがわかります ( DT列に報告されています)。
Galera Cluster は、各 MySQL サーバー ノードを読み取りと書き込みの両方を実行するマスター データベースとして提供します。 多くのアプリケーションでは、読み取りと書き込みの比率が非常に大きいため、マルチマスター データベース クラスターから得られる柔軟性と比較すると、同じテーブル行が複数のクライアントによって同時に更新されるリスクは完全に許容可能です。 同時書き込みが発生するリスクが高い状況では、2 つのオプションがあります。
この記事では、MySQL などの TCP (または UDP) アプリケーションの負荷分散の重要な側面をいくつか説明しました。 NGINX Plus は、トラフィックの種類に関係なく、パフォーマンス、信頼性、セキュリティ、スケールを備えたアプリケーションを配信できるように、フル機能の TCP/UDP ロードバランサーを提供します。
NGINX Plus をお試しいただくには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、使用事例についてご相談ください。
テスト環境は、分離され、繰り返し実行できるように仮想マシンにインストールされます。 ただし、物理的な「ベアメタル」サーバーにインストールできない理由はありません。
NGINX Plus 管理者ガイドを参照してください。
この例では、各ノードの Docker コンテナを使用して、単一のホストに Galera Cluster をインストールします。 以下の手順は、 「Getting started Galera with Docker」から引用したもので、 Docker EngineとMySQL コマンドライン ツールの両方がすでにインストールされていることを前提としています。
Docker イメージによって各 Galera コンテナにコピーされる基本的な MySQL 構成ファイル ( my.cnf ) を作成します。
Galera の基本 Docker イメージをプルします。
$ sudo docker pull erkules/galera:basic
最初の Galera ノード ( node1 ) を作成し、デフォルトの MySQL ポートを 33061 として公開します。
$ sudo docker run -p 33061:3306 --detach=true --name node1 -h node1 erkules/galera:basic --wsrep-cluster-name=local-test --wsrep-cluster-address=gcomm://
2 番目の Galera ノード ( node2 ) を作成します。 MySQL ポートは 33062 として公開され、クラスター間通信のためにnode1にリンクされます。
$ sudo docker run -p 33062:3306 --detach=true --name node2 -h node2 --link node1:node1 erkules/galera:basic --wsrep-cluster-name=local-test --wsrep-cluster-address=gcomm://node1
node2と同じ方法で、3 番目で最後の Galera ノード ( node3 ) を作成します。 MySQL ポートは 33063 として公開されます。
$ sudo docker run -p 33063:3306 --detach=true --name node3 -h node3 --link node1:node1 erkules/galera:basic --wsrep-cluster-name=local-test --wsrep-cluster-address=gcomm://node1
ホストからクラスターへのリモート アクセスに使用できるnginxというユーザー アカウントを作成します。 これは、Docker コンテナ自体からmysql(1)
コマンドを実行することによって実行されます。
$ sudo docker exec -ti node1 mysql -e"'plus' によって識別される 'nginx'@'172.17.0.1' に *.* のすべての権限を付与します"
TCP プロトコルを使用して、ホストから Galera クラスターに接続できることを確認します。
$ mysql --protocol=tcp -P 33061 --user=nginx --password=plus -e "SHOW DATABASES" mysql: [警告] コマンドライン インターフェイスでパスワードを使用すると安全でない可能性があります。 +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+
最後に、別のクラスター ノードに対して同じコマンドを実行し、 nginxユーザー アカウントが複製され、クラスターが正しく機能していることを確認します。
$ mysql --protocol=tcp -P 33062 --user=nginx --password=plus -e "SHOW DATABASES" mysql: [警告] コマンドライン インターフェイスでパスワードを使用すると安全でない可能性があります。 +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"