軽量アプリケーションサーバ NGINX Unitを触ってみる

こんにちは、GMOソリューションパートナー媒体開発本部のN.Sです。

先日NGINX社より軽量アプリケーションサーバNGINX Unitのベータ版リリースがありました。
各言語毎のアプリケーションサーバ運用を一本化出来るメリットがありそうですが、
今後の選択肢として、導入の手間、操作感、パフォーマンスはどうなの?という事で簡単に触ってみました。

NGINX Unitとは?

  • https://www.nginx.com/products/nginx-unit/
  • 2017.9.7に発表されたばかりのNGINX社製 軽量アプリケーションサーバ。
  • 2017.9.28現在でv0.1ベータ版、特徴は主に以下です。
    • RESTful APIやJSON経由でサービス無停止でリアルタイムに設定変更が出来る
    • 複数言語に対応(PHP, Python, Go対応、今後Java, Ruby, Node.jsにも対応予定
    • 将来的に既存の商用NGINX + NGINX Unit にGUI管理機能のNGINX Controllerを加えて統合プラットフォームを作る構想がある
      https://oss.sios.com/nginx-ch/nginxconf2017

 

CentOS7コンテナにNGINX Unitをインストールしてみる

NGINX Unit導入の前提環境は以下です。

  • Linux2.6以上
  • Python 2.6, 2.7, 3
  • PHP 5系、7系
  • Go 1.6以上

今回はテスト環境として以下を使用しました。

  • Dockerコンテナ環境構築
  • ホストOSは、ローカルPCにVagrant+ VirtualBoxで構築したCentOS7.4
  • コンテナ環境はCentOS 7.4.1708/Linux3.10.0 + NGINX Unit 0.1 + PHP5.4.45

今回行う導入・設定を実施済のDockerコンテナ環境は以下です。
とりあえず環境を見たい方はこちらをご覧ください。
※実行手順はリンク先の「起動方法」参照

https://hub.docker.com/r/oshou/docker-centos7-unit/

1. CentOS7コンテナ起動、コンソールログイン

管理者モードでCentOSプレーンのコンテナ起動起動、NGINX Unitで動かすサンプルアプリケーション用にport8300を通しておきます。

2. NGINX Unit用レポジトリ作成

CentOS7 or Ubuntu16.04TLSはunitインストールパッケージが提供されているので、今回はそちらを使います。

3. NGINX Unitインストール

4. 設定用ツール インストール

Unitデーモンの設定は、UNIXドメインソケットへのリクエストにより行うので、
curl(v7.40以上)をインストールします。
※v7.40以上でないとドメインソケット対応オプション –unix-socketが使えません。
CentOS7では以下手順で別途レポジトリを定義してインストールしました。
https://www.rootlinks.net/2017/09/21/update-curl-7-29-to-7-55-on-centos-7-with-city-fan-repo/

5. NGINX Unitデーモンの起動

デーモンの起動を確認します。
unitdは管理用のTCPポート等は存在せず、UNIXドメインソケット通信により設定を行います。

Unitの初期設定をしてみる

1. 設定用jsonファイルの作成

listeners(待機するTCPポート設定)とapplications(遷移先のアプリケーション設定)は必須なのでそれぞれ以下要領で指定します。
詳しいパラメータは下記を参照下さい。
https://unit.nginx.org/docs-configuration.html#listener-and-application-objects

2. 設定用jsonファイルをunitデーモンに投入

リクエストメソッド、設定用jsonファイル、socketファイル、配置先URLをそれぞれ指定してリクエストを行います。
socketファイルはデフォルトだと/var/run/control.unit.sockです。

設定は以上です!簡単ですね。
注意点としては以下です。

  • curlがv7.40以上になっている事(–unix-socketオプション指定でエラーが発生しない事)
  • socketファイルのパスが正しく指定されている事(デフォルトだと/run/control.unit.sock)
  • HTTPメソッドが正しく設定されている事

3. 設定反映の確認

それでは正しく動作しているか確認してみましょう。
設定内容は設定先URLにGETリクエストを送ることで確認できます。

反映直後から指定したTCPポートでリッスンされる事が確認出来ました。

DocumentRootの場所にphpinfo()表示用スクリプトを配置してみます。
http://[Docker親ホストIP]:8300/[スクリプト名]にアクセスして正しく表示された事が確認できました。

ちなみに複数サーバ設定時はlisteners, applicationsでそれぞれ並列表記します。
一覧性があり見やすいですね

一部設定を動的変更する場合はパラメータに対応した特定URLにPUTリクエストを送ります。
例えばworkersを20->30に変更する場合は、
http://localhostの/applications/sample_php/workers宛に更新データを-dオプションで送るだけで即反映されます。

 

簡易的なベンチマークを行ってみる

それではNGINXサーバ連携で置換え検討機会の多そうなphp-fpmと比較してみましょう。
テスト環境は以下です。

テスト環境

  •  比較環境
  • アプリケーションサーバは基本デフォルト設定、worker数MAX値だけ10で統一
  • サンプルスクリプトは以下
  • Apache Benchで計測
  • 以下で計測(同時接続数100、総リクエスト数10000、keepaliveを使用しない)

テスト結果

APサーバ スループット(req/s) 平均レスポンスタイム(ms/req) エラー率(%)
NGINX Unit 423.12 2.363 0
php-fpm 571.13 1.751 0

不本意ながらphp-fpmの方が早い!という結果が出てしまいました、、、
実施後の所感としては以下でした。

  • 同一ホストでコンテナ環境もミドル部分以外は統一しているため、他影響ではなくアプリサーバ側の性能差が取れていそう
  • ps aux等で見るとNGINX Unitは子プロセスのメモリ効率が悪い印象を受けた。RSS=実際に使用した物理メモリ がphp-fpmの約4倍だった。
    • php-fpm側が5.94MB、NGINX Unit側が26.04MB程度
  • php-fpmのpm.start-serverにあたるものが無いため初回コストがかかっている
  • 他Go、Python言語等でも性能差比較してみたい

まとめ

  • CentOS7、Ubuntu向けにパッケージ提供されているので導入は簡単、CentOS6系等は公式手順でソースインストールが必要
  • 比較的軽量でサクサク動く印象だが、本検証ではphp-fpmには及ばずでした。
    他言語でも比較して傾向を見たい所ですが、PHPに関してはメモリ効率部分で今後に期待したい所でした。
  • JSONベースの設定が使いやすい。
    一覧性が高く、config.jsonだけ抑えておけばOKな手軽さが良い。動的設定変更も可能。
    ただし、初回起動時に設定用JSONファイルを都度PUTリクエストする必要があるので注意
  • モニタリング、権限管理機能等は今後登場予定のNGINX Controller側で実装される(?)
    • https://oss.sios.com/nginx-ch/nginxconf2017
  • 複数言語でアプリケーションサーバを一本化、という事が出来そうですが、
    ベータ版という事であまり詳細なパラメータはまだ公開されていない模様。
    php-fpmで言う pm.start-server(初回起動時のワーカー数)やpm.max_requests (メモリリーク対応)、slowlog(スローログ取得)等にあたるものが今後出てくると嬉しい。