前回は、Phalconについての紹介をさせて頂きました。
今回は、nginx の設定値について触れていきたいと思います。

[Oculus]3D動画をストリーミング再生する方法 – 19 – の記事で、アップロード処理の改善のために nginx を利用するとお話ししましたが、nginx の細かい部分については、詳しく調査できておりませんでした。
同じWebサーバであるApacheも、動作させるために設定する各種パラメータによって処理速度等が変わりますので、nginx についても、同じことが言えると思います。
このため、今回はnginx のアップロードについて、主に設定値を変更することでの改善を行ってみましたので、その内容をまとめます。
特に重要と思われる部分を抜粋していますが、かなり細かいところまで設定を変更することができますので、利用しているサーバに合わせて、適時修正すると良いです。
■前提
nginx の性能を測定するために、CentOSのサーバを使いました。
以下のような環境です。
環境情報 | |
---|---|
OS | CentOS 6.8 |
CPU | Intel(R) Pentium(R) CPU G630 @ 2.70GHz |
CPU数 | 2 |
メモリ | 4GB |
■nginx のアップロード時の挙動を修正
nginx はデフォルト設定では、client_body_buffer_size(8KB)を超えるサイズのアップロードが行われた場合に、受信したRequestBodyの内容をHDDに保存します。
たとえば、THETAで撮影中の画像ファイルですと、80KB~100KBのサイズになりますので、たとえ1つずつアップロードしたとしても、RequestBodyのサイズが上限値を超えています。
また、保存されるのはRequestBodyであり、画像データではないので、このデータを直接利用することはできません。
アップロードが頻繁に行われるシステムですので、毎回RequestBodyをHDDに保存するのは処理速度の低下につながります。
そこで、アップロードの場合には、RequestBodyの内容をHDDに保存するのを止める為、nginx.conf 内で、対象となる location に対して、proxy_request_buffering を off に設定します。
■nginx で PHP を動かす時のこと
nginx は Apache と異なり、PHPを動作させるには別途、PHP-FPMを利用する必要があります。
nginx と PHP-FPM は別プロセスなので、プロセス間通信が必要ですが、このとき、TCP通信か、UNIXドメインソケット通信を利用します。
TCP通信の方を利用する場合は、別プロセスへのアクセスのために、TCP/IPを利用するためIPスタックを経由しますが、UNIXドメインソケットではそのような処理を行いません。
このため、UNIXドメインソケットの方が高速です。
UNIXドメインソケット通信は、同一マシン上のプロセス間通信にしか使えませんが、今回の用途であれば、この制約で、特に問題になることはありませんので、UNIXドメインソケットの方を利用します。
■nginx の設定の修正
・worker_processes
サーバのCPU数に設定します(このサーバの場合は2)
・worker_connections
1プロセスが処理できるコネクション数の上限
このサーバでは、プロセスが開けるファイルディスクリプタの上限が「1024」だったので、
この値についても、同じ値で設定しました。
・worker_rlimit_nofile
1プロセスあたりの最大ファイルディスクリプタ数
調べたところ、worker_connections の3~4倍程度の値にするのが一般的であったので
今回は4096としました。
・multi_accept
リクエストを同時に受け付けられるようにするため、ON
■PHP-FPM の設定の修正
・pm
dynamic(メモリの動的割り当て)、static(メモリの静的割り当て)のどちらかを選択します。
dynamic の方は、必要な時にプロセスを生成する設定です。
サーバ内で他に処理すべきことがある場合には、そちら側でもメモリを利用したいので、
必要時以外はプロセス数を減らして、メモリを空けておくという意味で、dynamicを設定します。
static の方は、nginx 起動時に、設定されている数分のプロセスを生成します。
プロセスの生成/破棄が行われないので、nginx 自体は dynamic に比べると高速に動作しますが、
サーバのスペックがあまり高くなかったり、他の処理にもメモリを使いたい場合には dynamic の方が良いです。
今回は、Webサーバ上で動画作成処理等の、重た目の処理を行う予定があるため、dynamic にしています。
・pm.max_children
作成される子プロセスの最大数。
プロセス数を増やしすぎるとメモリが枯渇します。
逆に、高スペックのサーバであれば、ここの数値を高くすることで、
より多くのリクエストを処理できるようになります。
今回は、10としています。
・pm.min_spare_servers / pm.max_spare_servers
アイドル状態のサーバープロセス数。
どちらも dynamic 設定で利用します。
min_spare_serversの方は、最低でも起動しておくプロセス数。
max_spare_serversの方は、各プロセスの処理完了時に、本値を超えていた場合は
プロセスを終了する、という意味になります。
いずれも、max_children 以下の値とする必要があります。
・pm.max_requests
各子プロセスが、再起動するまでに実行するリクエスト数。
あまり小さすぎる値にすると、プロセス破棄/生成処理にCPUやメモリを使うことになりますが、
設定しておくと、メモリリーク対策になります。
今回は、500と設定しました。
■測定
3台のWindowsPCから、Apache JMeterを使用して性能を測定しました。設定した負荷内容は以下のとおりです。
設定内容 | |
---|---|
通信設定 | 100KBの画像ファイル×10を1リクエストでアップロードする |
スレッド数 | 1 |
Ramp-Up期間 | 1 |
ループ回数 | 100 |
改善前、改善後のスループット/平均処理時間/90%Line処理時間は、以下の通りです。
スループット | 平均処理時間 | 90%Line | |
---|---|---|---|
改善前 | 1.56pv/s | 654ms | 961ms |
改善後 | 1.76pv/s | 568ms | 800ms |
平均で1リクエストあたり100ms以上、90%Lineでは150ms程、処理時間が改善されています。
■まとめ
実際に、今回紹介した設定値を調整した感想としては、設定値を変更すること自体は非常に容易ですが、nginx と PHP-FPM の2つに対して設定を行う必要があることから、Apache と比較すると調整が難しく感じました。
今回の改善については、通常のWebサーバとして利用する分には、設定値を変更する前でも特に問題無い速度が出ていたこと、改善されたのも100msと、体感できる程のものではなかったことから、劇的にアップロードのパフォーマンスが良くなるというものではないと思いました。
ただし、3Dパノラマ動画をリアルタイム配信するために、大量の画像や音声をアップロードし続けるという今回の仕組みで利用する場合は、アップロードに要する時間は短ければ短いほどよく、とても重要な部分になります。
このため、システムを作り上げた後、性能の測定と、設定値のチューニングを行うべきだと思いました。
特に、重要と思う設定値は、PHP-FPM 側のプロセス数に関連するものです。
Web専用のサーバを用意した場合は、CPUやメモリの大半を nginx / PHP-FPM に回すことができるため、プロセス数を大幅に増やすことで、更なる改善を行うことができます。
また、今回は測定しておりませんが、アップロードではなく、ダウンロード側についても、今回紹介した設定値で改善することができます。
特に、画像データ等のリソースデータをダウンロードするケースのように、PHPを動かす必要がない場合には、nginx の設定のみで改善が見込めます。
nginx をより高速に動かしたいという場合には、参考にしてみてください。
最後までご覧いただき、ありがとうございました。
弊社では全国各地の請負い(ご自宅)で作業協力頂ける、フリーランスエンジニアの方を常時探しております。
ご興味ある方は、お気軽にお問い合わせ下さい。