Edited at

php-fpmを使ってphpを快適にfastcgiで実行する

More than 3 years have passed since last update.


fpmを使ってphpをfastcgiで実行する

phpをモジュール版ではなくcgi版でインストールしたが、そのまま使うとパフォーマンスの心配もあり、またセキュリティ的にも不安なのでphp-fpmを使用してfastcgiで実行する。

cgi版をそのまま使用すると一つのプロセスを1処理で使って破棄、また処理の要求があった時にプロセスを作成して・・・といった無駄なオーバーヘッドがあり非常にコストがかかる事になってしまいます。それに対してphp-fpmだとプロセスを使いまわししてくれます。そのため、オーバーヘッドがなくなるばかりか、モジュール版でなくともopcacheが効くようになるという効果も得る事ができます。

更にモジュール版と違ってサイトごとに実行ユーザを変更するなど色々調整ができます。大変使いやく応用が効きますのでおススメです。

※モジュール版でも各サイト毎にWEBサーバを立ち上げ、リバースプロキシを使えば実現できるのですが、、fpmのようにお手軽ではないと考えています。


php-fpmのインストール

php5.6を既にインストールしてる前提です。

今回はopcacheも一緒に入れました。使用しているサーバがawsなのでamazonのリポジトリに5.6がありました。もしも5.6がない場合はremi-php56リポジトリなどを使ってください。

yum install php56-opcache.x86_64 php56-fpm.x86_64


設定

yumのパッケージでインストールした場合、設定ファイルは

/etc/php-fpm.conf



/etc/php-fpm.d/配下に置いた*.confが使用されます。

今回はセキュリティを上げたいので各ドメインごとにphpの実行ユーザを分けたいと思います。

また、本来なら専用のサーバを用意したいのですが・・趣味なのでWEBサーバと同じサーバに入れます。

その為、ソケット通信にしています。

具体的には下記のような構成を実現します。

ドメイン名
www.hoge.jp
www.hoge.com

ポート
socket通信
socket通信

アクセス許可
localhost
localhost

実行ユーザ
www.hoge.jp
www.hoge.com

ドキュメントルート
/var/www/www.hoge.jp/doc_root/

/var/www/www.hoge.com/doc_root/

phpログフォルダ
/var/www/www.hoge.jp/log/

/var/www/www.hoge.com/log/

sessionフォルダ
/var/www/www.hoge.jp/session/

/var/www/www.hoge.com/session/

SOAPキャッシュフォルダ
/var/www/www.hoge.jp/session/

/var/www/www.hoge.com/wsdlcache/


設定パラメータ

pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_serversは負荷テストなどをしながら調整するしかないと思います。

サイトやサーバーごとによって変わると思うので絶対的な正解はないと思います。

パラメータ名
説明

[xxx]
プロセスプールになります。このプールの単位でlistenや実行ユーザの切り替えが可能です。今回はドメインごとにプールを切り分けます。

listen
FastCGI リクエストを受け入れるアドレス。 'ip.add.re.ss:port', 'port', '/path/to/unix/socket' 形式の構文が使えます。 このオプションは、各プール単位で必須となります。

listen.allowed_clients
接続を許可されている FastCGI クライアントの ipv4 アドレス一覧。オリジナル版 PHP FastCGI (5.2.2+) における環境変数 FCGI_WEB_SERVER_ADDRS と同じです。 tcp でリスンするソケットに対してのみ意味をなします。 書くアドレスはカンマ区切りで指定します。この値を空にしておくと、任意の ip アドレスからの接続を許可します。 デフォルト値: 任意の ip アドレスを許可。

listen.owner
unix ソケットを使う場合に、そのパーミッションを設定します。Linux では、 読み書きアクセス権限を設定しないとウェブサーバーからの接続を受け付けることができません。 デフォルト値: ユーザーとグループは実行しているユーザーと同じ、モードは 0660

listen.group
listen.ownerと同じ。socketのパーミッション。

listen.mode
listen.ownerと同じ。socketのパーミッション。

user
FPM プロセスの unix ユーザー。このオプションは必須です。セキュリティの為にも専用ユーザを用意した方が良いと思います。

group
FPM プロセスの unix グループ。未設定の場合は、デフォルトのユーザーのグループを使います。セキュリティの為にも専用グループを用意した方が良いと思います。

pm
プロセスマネージャが子プロセスの数を制御する方法を選択します。 使用可能な値: static, ondemand, dynamic このオプションは必須です。

pm.max_children
pm が static の場合は作成される子プロセスの数、 pm が dynamic の場合は作成される子プロセスの最大数。 このオプションは必須です。このオプションは、同時に処理できるリクエストの最大数を設定します。 mpm_prefork での ApacheMaxClients ディレクティブみたいなイメージです。

pm.start_servers
起動時に作成される子プロセスの数。pm が dynamic の場合にのみ使います。デフォルト値: min_spare_servers + (max_spare_servers - min_spare_servers) / 2

pm.min_spare_servers
アイドル状態のサーバープロセス数の最小値。 pm が dynamic の場合にのみ使います。 また、この場合には必須となります。アイドル状態のプロセス数がこれよりも減った場合に新たなプロセスが作成されます。

pm.max_spare_servers
アイドル状態のサーバープロセス数の最大値。 pm が dynamic の場合にのみ使います。 また、この場合には必須となります。アイドル状態のプロセス数がこれよりも増えた場合にアイドルなプロセスをkillします。

pm.max_requests
各子プロセスが、再起動するまでに実行するリクエスト数。 サードパーティのライブラリにおけるメモリリークの回避策として便利です。 再起動せずにずっとリクエストを処理させる場合は '0' を指定します。 PHP_FCGI_MAX_REQUESTS と同じです。デフォルト値: 0

pm.status_path
FPM の情報ページを見るための URI。この値を省略した場合は、どの URI も情報ページとは見なされません。デフォルト値: なし

ping.path
FPM のモニタリングページをコールするための ping URI。この値を省略した場合は、どの URI も ping ページとは見なされません。これを使うと、 FPM が生きていて応答するかどうかを外部から確かめることができます。 この値の最初はスラッシュ (/) で始めなければならないことに注意しましょう。

request_terminate_timeout
単一のリクエストを処理する際のタイムアウト。この時間を過ぎるとワーカープロセスが kill されます。 このオプションは、'max_execution_time' ini オプションが何らかの理由でスクリプトの実行を止められなかった場合に使われます。 値 '0' は 'Off' を意味します。 使用可能な単位: s(秒)(デフォルト), m(分), h(時間) あるいは d(日)、 デフォルト値: 0

request_slowlog_timeout
単一のリクエストを処理する際のタイムアウト。この時間を過ぎると PHP のバックトレースが 'slowlog' ファイルに出力されます。 値 '0' は 'Off' を意味します。 使用可能な単位: s(秒)(デフォルト), m(分), h(時間) あるいは d(日)、 デフォルト値: 0

slowlog
遅いリクエストを記録するログファイル。デフォルト値: #INSTALL_PREFIX#/log/php-fpm.log.slow

php_admin_flag
このドメイン独自で設定したい値をここに書くことができます。php.iniの設定を上書きするイメージです。

php_admin_value
このドメイン独自で設定したい値をここに書くことができます。php.iniの設定を上書きするイメージです。

php_value
このドメイン独自で設定したい値をここに書くことができます。php.iniの設定を上書きするイメージです。


ユーザ、ディレクトリの追加

ユーザはセキュリティ向上の為、ログインできないユーザにしておきます。

mkdir -p /var/www/www.hoge.jp/log

mkdir -p /var/www/www.hoge.jp/doc_root

mkdir -p /var/www/www.hoge.jp/session

mkdir -p /var/www/www.hoge.jp/wsdlcache

mkdir -p /var/www/www.hoge.com/log

mkdir -p /var/www/www.hoge.com/doc_root

mkdir -p /var/www/www.hoge.com/session

mkdir -p /var/www/www.hoge.com/wsdlcache

groupadd -g 2000 www.hoge.jp

groupadd -g 2001 www.hoge.com

useradd -u 2000 -g 2000 -N -s /sbin/nologin -M -d /var/www/www.hoge.jp www.hoge.jp

useradd -u 2001 -g 2001 -N -s /sbin/nologin -M -d /var/www/www.hoge.com www.hoge.com

chown -R www.hoge.jp:www.hoge.jp /var/www/www.hoge.jp

chown -R www.hoge.com:www.hoge.com /var/www/www.hoge.com


/etc/php-fpm.d/配下の設定ファイル

/etc/php-fpm.d/配下にドメインごとに設定ファイルを用意します。

(一つのファイルに複数のサーバを記載する事も可能です。)


/etc/php-fpm.d/www.hoge.jp.conf

[www.hoge.jp]

listen = /var/run/php-fpm/www.hoge.jp.sock
;listen.allowed_clients = 127.0.0.1
listen.owner = nginx
listen.group = nginx
listen.mode = 0600

user = www.hoge.jp
group = www.hoge.jp

pm = dynamic
pm.max_children = 40
pm.start_servers = 3
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 10000
pm.status_path = /operation/php-fpm/www.hoge.jp-status.php
ping.path = /operation/php-fpm/www.hoge.jp-ping.php

request_terminate_timeout = 600
request_slowlog_timeout = 100
slowlog = /var/www/www.hoge.jp/log/php-fpm/php-slow.log

php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/www/www.hoge.jp/log/php-fpm/php-error.log
php_value[session.save_handler] = files
php_value[session.save_path] = /var/www/www.hoge.jp/session
php_value[soap.wsdl_cache_dir] = /var/www/www.hoge.jp/wsdlcache



/etc/php-fpm.d/www.hoge.com.conf

[www.hoge.com]

listen = /var/run/php-fpm/www.hoge.com.sock
;listen.allowed_clients = 127.0.0.1
listen.owner = nginx
listen.group = nginx
listen.mode = 0600

user = www.hoge.com
group = www.hoge.com

pm = dynamic
pm.max_children = 40
pm.start_servers = 3
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 10000
pm.status_path = /operation/php-fpm/www.hoge.com-status.php
ping.path = /operation/php-fpm/www.hoge.com-ping.php

request_terminate_timeout = 600
request_slowlog_timeout = 100
slowlog = /var/www/www.hoge.com/log/php-fpm/php-slow.log

php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/www/www.hoge.com/log/php-fpm/php-error.log
php_value[session.save_handler] = files
php_value[session.save_path] = /var/www/www.hoge.com/session
php_value[soap.wsdl_cache_dir] = /var/www/www.hoge.com/wsdlcache



nginx側

nginx側はソケット通信を用いるので下記のようにします。


www.hoge.jpドメイン

fastcgi_pass   unix:/var/run/php-fpm/www.hoge.jp.sock;



www.hoge.comドメイン

fastcgi_pass   unix:/var/run/php-fpm/www.hoge.com.sock;



番外編apacheの場合

proxy_fcgi_moduleが使えるならproxy_fcgi_moduleを使おう

(2.4〜)


mod_fastcgiの場合

   FastCGIExternalServer /usr/sbin/php-fpm -socket /var/run/php-fpm/www.hoge.com.sock



proxy_fcgi_moduleの場合

   SetHandler  "proxy:unix:/var/run/php-fpm/www.hoge.com.sock|fcgi://localhost"



参考/抜粋/出典元

http://php.net/manual/ja/install.fpm.php

以上