こんにちはエンジニアの @hanhan1978 です。2017年9月6日にNginxがApplication Platformの「Unit」をリリースしました。 Introducing the NGINX Application Platform with Controller and Unit
世界中がザワザワしているようですが、特に日本はザワザワしているようで、Google Trendで調べて見たら日本が一番バズってます。 Nginx Unit - Google トレンド
PHP界隈でも、PHP-FPMに取って代わる&HTTPで通信できるモダンなアプリケーションサーバがついに登場か!?ということでザワザワしています。 自分も、Dockerコンテナ上でPHPアプリケーションを動かす最適解を勝手に探し求めている人間なので、もしかして「Unit」はPHPアプリケーションのコンテナ化を促す強い推進力になるかもとウキウキしてしまいました。
というわけで、「Unit」でひとまずLaravelのアプリケーションを動かしてみて、どんな構成で動かせばいいのか調べてみました。
UnitでLaravel動かす時の構成
サーバ構成図
Nginxを前段に配置して、*.php
のリクエストをReverse ProxyでUnitに振り分ける構成です。
※Ubuntu 16.04 (Xenial) を使って、Vagrant上に環境構築しました。
ハマったところ&分かったところ
1. アプリケーションサーバに対する誤解
完全に先入観による誤解だったのですが、Apache(mod_php)とか Tomcatみたいなイメージをしていました。つまりLaravelのアプリケーションを DocumentRootにおいてあげれば、静的ファイルも含めてよしなに処理してくれるだろうと思ったのですが、Unitが処理するのはPHPだけです。
イメージ的には、PHP-FPMと同様です。Unitの前段に静的ファイルを処理するWebサーバを配置する必要があります。今回の構成ではNginxを使いましたが、別にApacheでも何でも良いです。
2. PHPのextensionについて
Ubuntu版のUnitは、パッケージ管理ツールでインストールした libphpを利用しているようです。そのため、 apt-get install php7.0-mysql
とかしてextをインストールしてUnit再起動すれば、追加のextも普通に使えるようになりました。
個別にPHPをソースインストールしているような環境では、適切にヘッダファイル指定してUnitを再コンパイルする必要がありそうです。 この辺、どうやってPHPを実行しているのかとかは、もう少し詳細に調査したいところです。
3. Proxyの設定
FastCGIの時と違って、Reverse Proxyで処理を飛ばすので、ヘッダの情報を適切に引き継いで上げないとLaravel側がRoutingの判断をできません。
Laravelの場合は、X-Original-Url
でRequest URI
を渡してあげないと、全部 /
へのアクセスになってしまいます。
location ~ \.php$ { try_files $uri /index.php =404; proxy_pass http://unit_backend; proxy_set_header X-Original-Url $request_uri; proxy_set_header Host $host; }
認証でAuth Headerとか使う場合も Proxyの設定周りで引き継いで上げる必要があります。 この辺は、そもそもProxy使って構成を作ってる他言語界隈の情報や知見が使えるかと思います。
いきなりPHP-FPMからUnitに切り替えると、少しハマるかもしれません。
パフォーマンス測定してみた。
Nginx with PHP-FPM の場合と Nginx with Unit の構成で、パフォーマンス比較をやってみました。
構成 | リクエスト数/30sec |
---|---|
Nginx with PHP-FPM | 4202 |
Nginx with Unit | 2921 |
いずれも siegeで並列度150のリクエストで最も多くのリクエストを処理しましたが、軍配はPHP-FPMに上がりました。 Unitは、workerを増やしてもこれ以上は性能が引き出せず。
まだまだ、パフォーマンス面では改善の余地がありそうです。
※余談ですが、並列度を高めていった時に、PHP-FPMだと少しずつエラー率が上がったのですが、Unitは一気に崩れるような傾向がありました。
コンテナ作成者目線で考えると
現状のPHPアプリケーションに対してはPHP-FPMの置き換え候補という感じがしました。
DockerでPHPアプリのコンテナを作っている人は、Apache(mod_php)のコンテナにするか、NginxとPHP-FPM(複数プロセス)を同居させるコンテナを作ることが多いのですが、Unitも単体で静的ファイルを処理できるわけではないので、 Nginx + Unit という構成でコンテナを作ることになりそうです。
UnitだけでPHPアプリを良しなに処理できるかも最高〜とか勝手に妄想してましたが、そうはなりませんでした。残念。
まとめ
まだVersion 0.1 ということなので、まだまだこれからというアプリケーションサーバですが、多数の言語を動作させられたり、設定内容をcurlでAPIに直接食べさせたりするところに未来感を感じて、すごく楽しかったです。
まだ、POSTが出来なかったりとか、色々と不具合ありそうですが、HTTPで通信出来るPHPのアプリケーションサーバというのは、PHPerも待望していたものだと思いますので、応援していきたいと思います!
おまけ
UnitインストールのAnsible Playbook(For Ubuntu)抜粋
- name: install apt keys apt_key: url=http://nginx.org/keys/nginx_signing.key state=present - name: set repository apt_repository: repo='deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx' state=present - name: set repository apt_repository: repo='deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx' state=present - name: apt update apt: update_cache=yes - name: install nginx unit apt: name={{item}} with_items: - unit - name: ensure nginx unit start service: name=unitd state=restarted enabled=yes
Ansible使う方は、参考にどうぞ。UnitのReadMeに書いてある手順をPlaybookにしただけですが。