设为首页 收藏本站
查看: 1350|回复: 0

[经验分享] Apache httpd 2.4.x 使用 mod_proxy_fcgi 和 PHP-FPM 的方式

[复制链接]

尚未签到

发表于 2018-11-20 07:25:55 | 显示全部楼层 |阅读模式
  PHP-FPM 是一个简单可靠的 FastCGI 进程管理器(FastCGI Process Manager),从 PHP 5.3.3开始就成为了 PHP 的内置管理器。Apache 官方网站也提供了配置 Apache httpd 2.4.x 使用 mod_proxy_fcgi 和 PHP-FPM 运行 php 程序的基本方法和设置运行方式的简单介绍。可是折腾了一圈之后发现实际上这个东西还挺麻烦的,所以汇总记录下查找的资料以备查阅。
  为了省事,就以官方文档做模子了。基本的安装和配置已经在“更改 LAMP 执行方式为 PHP-FPM”一文中有记录。这里仅仅记录设置代理方式的问题。
  使用 PHP-FPM 就意味着不用 Apache 内置的 mod_php,也就是要在 Apache 之外处理 php 程序的解释运行问题。看起来是多引入了一个额外的程序 PHP-FPM,既占 CPU 又占内存。但是这样一来,因为 Apache 可以专心处理除 php 之外的静态网页及元素,反而 httpd 进程本身占用的 CPU 和内存可以显著降低,从而从整体上降低资源消耗。
  快捷目录

  •   PHP-FPM 监听方式
  •   Apache 发送 PHP 处理请求的方式
  •   四种处理方式举例

    •   SetHandler
    •   ProxyPassMatch
    •   ProxyPass
    •   Mod_Rewrite

  •   总结
1. PHP-FPM 监听方式
  官方文档提到的 PHP-FPM 监听方式(接收 Apache 转过去的处理 PHP 的请求的方式)有 2 个。这是在 PHP-FPM 的 pool 配置文件,如 /etc/php-fpm.d/www.conf 中设置的监听方式。分别如下,

  •   TCP socket (IP 和 port)
    listen = 127.0.0.1:9000  就表示使用 TCP socket 方式。
  •   Unix Domain Socket (UDS)(Apache 2.4.9 及以上版本才支持此方式),通过路径指明 socket 的位置 /path/to/unix/socket,例如,
    listen = /var/run/php-fpm/php-fpm.sock  就表示使用 UDS 方式。
      因为暂时 CentOS 7 中默认的还是 Apache 2.4.6,未曾测试这一方式,所以暂时就没有特别的记录了
2. Apache 发送 PHP 处理请求的方式
  原来的 mod_php 采用 SetHandler 的方式处理 php 文件并不需要特别的设置,因为在安装 PHP 的时候会自动在 Apache 的配置文件目录写入一个 php.conf 的配置文件,里面有告诉 Apache 处理 php 需要的操作:
  
     SetHandler application/x-httpd-php
  

  这是很方便的。因为只要 Apache 遇到 .php 类型的文件就会知道要让 mod_php 来解释运行。这种方式是在收到每个请求之后才处理的,所以可以用于全局。
  而对 PHP-FPM 来说,这种简单的、全局的处理方式,SetHandler 的方式,要到 Apache 2.4.9 中才会引入,参见 Les RPM de Remi – Blog。下面也会对此举例,且会放在第一,因为这正是水景一页想要使用的方式。
  进一步的,到了 Apache 2.4.10 之后,关于 mod_php 以及 PHP-FPM 的配置和冲突规避的逻辑判断,都会在默认配置里设置好,参见 Les RPM de Remi – Blog。不过逻辑判断什么的比较简单,现在水景一页都在用,就图个在 prefork 和 event 之间切换方便。关键在于 2.4.9 里引入的 SetHandler 处理方式。
  目前 Apache 转发代理的方式,也就是 Apache 发送 php 处理请求给 PHP-FPM 的方式,有 3 种:

  •   ProxyPass
  •   ProxyPassMatch
  •   带 [P] 参数的 mod_rewrite
  这样一来情况就变复杂了,2 x 3 的组合方式就是 6 种。也正是因为这个,如果要一一详细解释就会很麻烦,也很容易让人迷惑,所以官网上才给出了一个复杂度和灵活性都居中的解决方案作为例子(ProxyPassMatch)。
  下面分别针对 SetHandler、ProxyPassMatch、ProxyPass、mod_rewrite 举例。
3. 四种处理方式举例
3.1 SETHANDLER
  前面说了,这种处理方式的适应性最强:在 Apache 范围内部署一次之后,所有的虚拟主机  里的 PHP 文件都会由它来处理。可谓一劳永逸,跟 mod_php 的便利程度是一样的。当然,也就没法针对每个 VirtualHost 来控制 PHP-FPM 的运行用户和资源分配了。可惜需要到 Apache 2.4.9 才能用上,当然,或者自己打补丁也行 :P
  首先,设置 1 中的 IP:Port 监听方式,在 /etc/php-fpm.d/www.conf 中设置,
listen = 127.0.0.1:9000  然后,在前例的基础上,设置一个全局的,比如在 vhost.conf 中所有  之前,或者干脆放到 php.conf 里面,
  
         SetHandler "proxy:fcgi://127.0.0.1:9000"
  

  Ok,完成 :) 就是这么简单,所以水景一页很喜欢。
  另外,如果希望采用 UDS 方式监听的话,例如,
listen = /var/run/php-fpm/php-fpm.sock  可以照下面这么做,
  
    # we must declare a parameter in here (doesn't matter which) or it'll not register the proxy ahead of time
  
    ProxySet disablereuse=off
  

  

  
# Redirect to the proxy
  

  
    SetHandler proxy:fcgi://php-fpm
  

  但是,水景一页测试了一下,首先,Apache 启动错误,提示 ProxySet URL must be absolute! 而如果是,
unix:///var/run/php-fpm/php-fpm.sock|fcgi://php-fpm  就没有问题。其次,网页出现白板,页面源文件显示 php 没有运行而是直接显示源代码。
  如果是 Apache 2.4.10,还可以这么设置,
# Redirect to the proxy  

  
    SetHandler "proxy:unix:/var/run/php-fpm/php-fpm.sock|fgci://localhost"
  

  这个水景一页当然就还没有测试了。
3.2 PROXYPASSMATCH
  在前面切换 mod_php 到 PHP-FPM 一文中已经采用了这种方式。关键点在于:

  •   需要在每个  中分别设置,即使使用相同的 pool,也需要在设置的时候修改 pool 后面的 webroot 路径;
  •   有些特殊的网站网页地址 url 与系统文件路径 dir 之间匹配的问题,简单的一条 ProxyPassMatch 可能还不够,比如那个设置 phpMyAdmin 的例子(见上文)。
  还是假设采用 IP:Port 监听方式,同 3.1。
  然后,在每个  里面加入,
  
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/path/to/webroot/$1
  

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

  •   ProxyPassMatch
      只有满足特定正则模式的内容才会匹配并执行此规则,这里的模式是,
      ^/(.*\.php(/.*)?)$
      从网站(虚拟主机  的根目录开始,匹配任何以 .php 结尾,或者在 .php 之后紧跟一个 / 再跟别的内容的路径。
  •   ^ (caret) 和 $ (dollar)
      标志要匹配的路径的开始和结束
  •   ( )
      括号里的内容可以用 $1 来表示,以方便后面引用它。
  •   fcgi://127.0.0.1:9000
      通过 mod_proxy_fcgi 来转发的代理,使用 fastCGI 协议,转到 PHP-FPM 监听的端口。
      改变 IP 地址和/或端口号就可以要转到的不同的 pool。用这个可以实现服务器分流、均衡等。
  •   /path/to/your/documentroot/
      非常重要!必须与虚拟主机的路径匹配,且必须是对应 php 文件在操作系统中的绝对路径。否则会找不到文件(PHP Script File)。这也是 URL 地址重写的目的所在:将 URL 地址转换成 fcgi://127.0.0.1:9000 后面紧跟着的 php 文件绝对路径
  •   $1
      可以从原始请求扩展成整个请求路径的变量,这里指代前面外围 ( ) 里面匹配的那个路径(uri)
  这里之所以没有官网例子中的 DirectoryIndex /index.php,是因为我们已经设置过 DirectoryIndex index.php 了。所以,如果有的服务器没有这么配置,可能要像官网示例那么配置:
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/path/to/your/documentroot/$1  
DirectoryIndex /index.php
  当然,也可以用 UDS 方式,如果支持的话。这里就不再费事了。
3.3 PROXYPASS
  仅以采用 IP:Port 监听方式,同 3.1,来给个例子,
  
    ProxyPass fcgi://127.0.0.1:9000/path/to/webroot/
  
    ProxyErrorOverride on
  

  仍然需要在每个  中分别设置。可以放在  之后。可以看到,这个方法与 ProxyPassMatch 是一回事儿。
  简单情况下,ProxyPass 那一行最后没有那个 $1 无关紧要,ProxyPassMatch 也一样。注意是简单情况下
3.4 MOD_REWRITE
  这个方法,利用 mod_rewrite 的 P 标志将地址重写并传递给 mod_proxy。本来应该是挺好的,还可以用来解决这里提到的一个严重警告。可惜:

  •   mod_rewrite 页面写得很清楚,这个方法不支持持久连接(persistent connections);
  •   水景一页没办法使找到的几个例子正常工作,总是会导致 php 源代码直接展示在网页,或者网页的源文件里。
  既然不好,就不浪费版面了。如果大家有兴趣,可以看下面几个例子:

  •   http://serverfault.com/questions/398834/understanding-apache-2-4-mod-proxy-fcgi-and-rewriterules-in-htaccess
  •   http://serverfault.com/questions/450628/apache-2-4-php-fpm-proxypassmatch
  •   http://www.gossamer-threads.com/lists/apache/users/409168#409168
4. 总结
  捣鼓了这么多,来个推荐吧,免得大家跟我一样走弯路。
  从性能、方便程度而言,目前还是直接用 ProxyPassMatch 吧,直到 Apache 2.4.10,一次性切换到 SetHandler。这会是个比较好的路线。但是呢,考虑到 CentOS 上游 RedHat 官方的backporting 政策,Apache 2.4.10 很有可能需要到下一次大的系统升级,比如 CentOS 8 中才会加入。
  另外,关于 PHP-FPM 处理方式中的一个安全警告,值得一看。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-637111-1-1.html 上篇帖子: Vagrant中Apache或Nginx,修改css/js等静态文件不生效的解决方案 下篇帖子: apache禁止访问默认虚拟主机
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表