Linode VPS 上 CentOS 7 中改 LAMP 执行方式为 PHP-FPM

CentOS 7 已经发布,并且采用 Apache 2.4 作为默认的 Apache 组件。听说 Apache 2.4 的 Event 模式很不错,而且配套的 mod_proxy_fcgi 与 PHP 已经原生支持的 PHP-FPM 配合默契且性能很好,再加上 Google 的 mod_spdy 需要运行在 thread safe 的环境下,改用 CentOS 7 + Apache 2.4 + MariaDB + PHP + PHP-FPM 似乎就成为顺理成章的事情了。因为 phpMyAdmin 匹配 PHP-FPM 的配置与一般的虚拟主机稍稍不同,一并写上。

因为是在现成的 CentOS 7 + PHP + MariaDB + phpMyAdmin 的 LAMP 服务器上将使用 mod_php 的 Apache MPM prefork 模式改为使用 PHP-FPM 的 MPM event 模式,故而直接从安装 PHP-FPM 开始,然后设置 PHP-FPM 的 pool 配置文件,最后修改 Apache 的虚拟主机配置文件和设置 MPM event 运行参数。

需要注意的是,PHP-FPM 目前还不支持 http authentication

1. 安装 PHP-FPM

以 root 身份运行,或者 sudo 运行,

yum install -y php-fpm

安装 CentOS 发行版默认的 PHP-FPM 安装包。yum 会自动解决依赖包的安装问题。

产生以下2个配置文件:

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

前一个配置文件不需要修改。后一个就是所谓的 pool 了(好像有人称之为“代理池”?)。

2. 配置 PHP-FPM 的 pool

Pool 配置文件都在 /etc/php-fpm.d/ 目录下,可以有很多个,结构一样,名称不同,配置参数根据需要变化。

比如针对每个虚拟主机设置单独的配置文件。但是水景一页的这个 VPS 上只运行了几个自己的虚拟主机,而不是做共享主机使用,所以对几个网站使用了同一个 www.conf 的配置文件。php-fpm 的参数设置可以参考这里的说明,还有这里的示例

下面是水景一页目前在用的参数,还在测试调整当中:

pm = dynamic
pm.max_children = 4
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 10000

因为并不是用于做共享主机的,只运行自己的几个虚拟主机,应该不需要给每个虚拟主机创建一个 pool,所以这里给几个虚拟主机使用相同的 www pool。如果需要给每个虚拟主机建一个单独的 pool,请参考这篇文章

2014.12.21 更新,调整了一下 pm 参数。因为按照大家的建议,pm.max_children 最好与 CPU 核心数一致。另外修改了一个错误,之前 pool 的配置文件目录写错了。

3. 修改虚拟主机配置文件

涉及到 2 类文件,一是全局的 Apache 配置文件,一是针对每个虚拟主机(Virtual Host)的配置文件。

3.1 全局 APACHE 配置文件及 EVENT MPM 运行参数

首先,检查一下,如果有不同的话,需要将 /etc/httpd/conf/httpd.conf 中的

DirectoryIndex index.html

改为

DirectoryIndex index.php index.html index.htm

因为 event MPM 与 prefork MPM 的运行方式不同,参数设置也有不同。而且现在 CentOS 7 中安装 Apache 之后在默认的配置文件 /etc/httpd/conf/httpd.conf 中都没有默认的参数了(连之前 prefork 的默认参数都被拿掉了)。所以从方便实用的角度考虑,水景一页推荐自己创建一个 /etc/httpd/conf.d/common.conf 文件来放置这类全局的、httpd.conf 中又没有的参数。

下面是水景一页目前正在使用,但还在测试观察和优化的 event MPM 运行参数,仅供参考:

<IfModule mpm_event_module>
  StartServers 1
  ServerLimit  8
  MinSpareThreads 25
  MaxSpareThreads 50
  ThreadsPerChild 25
  MaxRequestWorkers 200
  MaxConnectionsPerChild 10000
  # 由 500 调到 10000,因为访问量小,实际上就 1 个 server 在工作
 
  Timeout 30
  KeepAlive On
  MaxKeepAliveRequests 100
  # 2 or 3 for prefork, but event or worker can deal with it cleverly, maybe 15?
  KeepAliveTimeout 5
</IfModule>

# For Fallback
<IfModule mpm_prefork_module>
 StartServers 8
 MinSpareServers 8
 MaxSpareServers 12
 MaxClients 50
 ServerLimit 50
 MaxRequestsPerChild 1000
 
 Timeout 30
 KeepAlive On
 MaxKeepAliveRequests 100
 # 2 or 3 for prefork
 KeepAliveTimeout 2
</IfModule>

ServerSignature Off
ServerTokens Prod

另外可能需要提醒一下,水景一页目前使用的 Linode VPS 是 1G RAM,基本上就是运行这个网站了。

3.2 修改虚拟主机配置文件

然后还需要修改虚拟主机配置文件中的设置,例子中用的虚拟主机配置文件名是 vhost.confvhostssl.conf(针对 SSL 加密连接访问的配置)。这里就不弄太多例子了,原始配置请参考之前安装配置 LAMP 服务器的文章。

水景一页这个 VPS 不是给共享服务器而是纯粹自用的服务器,只有为数不多的几个虚拟主机,所以几个虚拟主机都在同一个文件中。总之是,需要对每个 VirtualHost 里的内容都做修改:在 DocumentRoot 那一行前面增加一段,

<IfModule mpm_event_module>
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/srv/www/local/html/$1
</IfModule>

红色字体部分要特别注意,需要与每个 DocumentRoot 后面的路径一致。

在 CentOS 中,虚拟主机配置文件存放在 /etc/httpd/conf.d 目录下。例如使用 mod_php 时候其中一个 Virtual Host 的配置(参考这里):

<VirtualHost *:80>
    ServerAdmin admin@cnzhx.net
    ServerName local.cnzhx.net
    <IfModule mpm_event_module>
        ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/srv/www/local/html/$1
    </IfModule>
    DocumentRoot /srv/www/local/html
    <Directory "/srv/www/local/html/">
        # protect wpconfig.php
        <files wp-config.php>
            Require all Denied
        </files>
        RewriteEngine on
        # BEGIN WordPress
        … … …
        # END WordPress
    </Directory>
ErrorLog "|/usr/sbin/rotatelogs /srv/www/logs/%Y%m%d.www.error.log 86400 480"
CustomLog "|/usr/sbin/rotatelogs /srv/www/logs/%Y%m%d.www.access.log 86400 480" combined
</VirtualHost>

前面提到过,phpMyAdmin 的虚拟主机文件设置稍稍有些不同,需要在上面增加的那一句声明下面再增加一句包含 phpMyAdmin 目录的声明,如下面的蓝色字体部分,

<IfModule mpm_event_module>
    ProxyPassMatch ^/phpMyAdmin/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/srv/www/phpmyadmin/public_html/phpMyAdmin/$1
    ProxyPassMatch ^/phpMyAdmin((.*)?/)$ fcgi://127.0.0.1:9000/srv/www/phpmyadmin/public_html/phpMyAdmin$1index.php
</IfModule>

其它保持不变。

同时,还需要注释掉 /etc/httpd/conf.d/php.conf 中的一些内容,或者做类似下面的条件判断处理:

<IfModule mpm_prefork_module>
#
# Apache specific PHP configuration options
# those can be override in each configured vhost
#
php_value session.save_handler "files"
php_value session.save_path "/var/lib/php/session"
</IfModule>

否则会与 PHP-FPM 中的配置冲突。如果还配置了其它的 php_value 和 php-flag 也都需要做类似处理。

4. 收尾、运行

现在,只需要将 /etc/httpd/conf.modules.d/00-mpm.conf 中的

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

前面加上 # 注释掉,然后将,

#LoadModule mpm_event_module modules/mod_mpm_event.so

前面的 # 去掉。

如果曾经优化过 Apache 的模块,还需要检查一下 /etc/httpd/conf.modules.d/00-proxy.conf 文件中的,

LoadModule proxy_module modules/mod_proxy.so

LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

确保它们前面没有 #。

再重启 PHP-FPM 和 HTTPD 服务就可以了,

systemctl restart php-fpm
systemctl restart httpd

5.参考文章

以下是一些比较重要的参考文章:

©

本文发表于水景一页。永久链接:<http://cnzhx.net/blog/centos-7-mod_php-to-php-fpm/>。转载请保留此信息及相应链接。

10 条关于 “Linode VPS 上 CentOS 7 中改 LAMP 执行方式为 PHP-FPM” 的评论

  1. 引用通告: Apache + PHP-FPM 与 Mod_deflate | 水景一页

  2. 引用通告: Apache + PHP-FPM 与 WordPress 多站点问题 | 水景一页

    • 具体的参数跟服务器性能和需要来调整。先设定一个保守的数值,初始值可以参考网上的文章里给的参数,再根据运行情况慢慢调整,总能找到合适的。即使是经验丰富的管理员也不能说一下子就给出优化的参数吧。

  3. 楼主我有个问题啊,您文章里说PHP-FPM 目前还不支持 http authentication ! 是说只有apache不支持吗?我装了xcache到了进管理界面验证密码的确进不去,是说不支持http authentication 吧?
    但是为什么nginx同样装了php-fpm到了xcache管理界面验证密码却能进去呢?
    所以您说的php-fpm不支持http authentication 指的是apache还是nginx? 还有现在php-fpm支持了吗?

      • 已经解决了,非常感谢楼主!困扰了我好久的问题。。 还有楼主您如果方便的话可否发个QQ到我邮箱,以后有问题还希望能和您请教,非常感谢。 邮箱hao****8@gmail.com

        • 直接留邮箱地址会有被垃圾邮件者收集的风险,已隐藏。
          如果有问题需要帮忙解决,可以在水景一页的论坛中发帖子,我会尽力提供帮助。其时效性不比QQ差。再说了,我已经很久很久没有登录过QQ了,而且还有时差问题。请理解。

  4. 引用通告: CentOS 7 / RHEL 7 上安装 LAMP + phpMyAdmin | 水景一页

雁过留声,人过留名

您的电子邮箱地址不会被公开。 必填项已用 * 标注

特别提示:与当前文章主题无关的讨论相关但需要较多讨论求助信息请发布到水景一页讨论区的相应版块,谢谢您的理解与合作!请参考本站互助指南
您可以在评论中使用如下的 HTML 标记来辅助表达: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>