こんにちは、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を通しておきます。
1 2 |
$ docker run --name unit -dit -p 8300:8300 --privileged centos:7 /sbin/init $ docker exec -it unit /bin/bash |
2. NGINX Unit用レポジトリ作成
CentOS7 or Ubuntu16.04TLSはunitインストールパッケージが提供されているので、今回はそちらを使います。
1 2 3 4 5 6 7 8 |
$ vi /etc/yum.repos.d/unit.repo ------------------------------------------------------------------------------------------- [unit] name=unit repo baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/ gpgcheck=0 enabled=1 ------------------------------------------------------------------------------------------- |
3. NGINX Unitインストール
1 |
$ yum install unit -y --enablerepo=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/
1 2 3 |
$ yum install -y epel-release $ rpm -Uvh http://www.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-1-13.rhel7.noarch.rpm $ yum install -y libcurl --enablerepo=city-fan.org |
5. NGINX Unitデーモンの起動
デーモンの起動を確認します。
unitdは管理用のTCPポート等は存在せず、UNIXドメインソケット通信により設定を行います。
1 2 3 4 5 6 |
[root@af0b9600d27e /]# systemctl start unitd [root@af0b9600d27e /]# ps aux | grep unit | grep -v "grep" root 237 0.0 0.0 16180 620 ? Ss 17:26 0:00 unit: main [/usr/sbin/unitd --log /var/log/unitd.log --pid /run/unitd.pid] nobody 239 0.0 0.0 16180 672 ? S 17:26 0:00 unit: controller nobody 240 0.0 0.0 16180 432 ? S 17:26 0:00 unit: router [root@af0b9600d27e /]# |
Unitの初期設定をしてみる
1. 設定用jsonファイルの作成
listeners(待機するTCPポート設定)とapplications(遷移先のアプリケーション設定)は必須なのでそれぞれ以下要領で指定します。
詳しいパラメータは下記を参照下さい。
https://unit.nginx.org/docs-configuration.html#listener-and-application-objects
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ vi /etc/unit/config.json ``` { "listeners": { "*:8300": { "application": "sample_php" } }, "applications": { "sample_php": { "type": "php", "workers": 20, "root": "/var/www/html", "index": "index.php" } } } ``` |
2. 設定用jsonファイルをunitデーモンに投入
リクエストメソッド、設定用jsonファイル、socketファイル、配置先URLをそれぞれ指定してリクエストを行います。
socketファイルはデフォルトだと/var/run/control.unit.sockです。
1 2 3 4 |
$ curl -X PUT -d @/etc/unit/config.json --unix-socket /var/run/control.unit.sock http://localhost/ { "success": "Reconfiguration done." } |
設定は以上です!簡単ですね。
注意点としては以下です。
- curlがv7.40以上になっている事(–unix-socketオプション指定でエラーが発生しない事)
- socketファイルのパスが正しく指定されている事(デフォルトだと/run/control.unit.sock)
- HTTPメソッドが正しく設定されている事
3. 設定反映の確認
それでは正しく動作しているか確認してみましょう。
設定内容は設定先URLにGETリクエストを送ることで確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[root@edc89762a40b /]# curl -X GET --unix-socket /var/run/control.unit.sock http://localhost/ { "listeners": { "*:8300": { "application": "sample_php" } }, "applications": { "sample_php": { "type": "php", "workers": 20, "root": "/var/www/html", "index": "index.php" } } } |
反映直後から指定したTCPポートでリッスンされる事が確認出来ました。
1 2 3 4 |
[root@edc89762a40b /]# netstat -pantu Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8300 0.0.0.0:\* LISTEN 82/unit: router |
DocumentRootの場所にphpinfo()表示用スクリプトを配置してみます。
http://[Docker親ホストIP]:8300/[スクリプト名]にアクセスして正しく表示された事が確認できました。
ちなみに複数サーバ設定時はlisteners, applicationsでそれぞれ並列表記します。
一覧性があり見やすいですね
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
{ "listeners": { "*:8300": { "application": "sample_php" }, "*:8400": { "application": "sample_python" }, "*:8500": { "application": "sample_go" } }, "applications": { "sample_php": { "type": "php", "workers": 20, "root": "/var/www/html/php", "index": "index.php" }, "sample_python": { "type": "python", "workers": 10, "path": "/var/www/html/sample_python" }, "sample_go": { "type": "go", "user": "www-data", "group": "www-data", "working_directory": "/var/www/html/sample_go", } } } |
一部設定を動的変更する場合はパラメータに対応した特定URLにPUTリクエストを送ります。
例えばworkersを20->30に変更する場合は、
http://localhostの/applications/sample_php/workers宛に更新データを-dオプションで送るだけで即反映されます。
1 2 3 4 |
[root@3bb8c9f41cb5 /]# curl -X PUT -d '30' --unix-socket /run/control.unit.sock http://localhost/applications/sample_php/workers { "success": "Reconfiguration done." } |
簡易的なベンチマークを行ってみる
それではNGINXサーバ連携で置換え検討機会の多そうなphp-fpmと比較してみましょう。
テスト環境は以下です。
テスト環境
- 比較環境
- NGINX v1.13.5 + NGINX Unit v0.1
https://hub.docker.com/r/oshou/docker-centos7-unit - NGINX v1.13.5 + php-fpm v5.4.45
https://hub.docker.com/r/oshou/docker-centos7-phpfpm-php54
- NGINX v1.13.5 + NGINX Unit v0.1
- アプリケーションサーバは基本デフォルト設定、worker数MAX値だけ10で統一
- サンプルスクリプトは以下
12<?phpphpinfo() - Apache Benchで計測
- 以下で計測(同時接続数100、総リクエスト数10000、keepaliveを使用しない)
1$ ab -n 10000 -c 100 -k http://localhost/info.php
テスト結果
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(スローログ取得)等にあたるものが今後出てくると嬉しい。