最近为了降低下网络运行成本,在 AWS 上用教育折扣开了服务器,搬了些托管业务过去。兼容为本,自然是 LAMP,不过因为这些年 Apache 2.4 的 event MPM 也算能用了(SetHandler + If 块判断文件存在,完美),加上 http2 不支持 Prefork MPM,就开了 PHP-fpm。

都配完了,没事看 PHP-fpm 的状态页面,总是会看到有进程在 reading header 的状态,而且显示持续时间很长。我以为是什么异常情况,PHP 自动停进程失败了,于是就设置了超 1 分钟强退进程,结果 php-fpm 的日志很快就被这些强退错误占满了。

仔细看日志,退出的时候执行的程序路径之类的参数都是空(还有一个是空格),我以为是 BUG,于是开了 Apache 和 php-fpm 的 debug 日志看,甚至翻了 PHP 的源代码(才发现那个空格是日志拼接字符串产生的),还是看不出什么头绪。不过,都是 Apache 关闭了请求之后 PHP 接着自己跑。

逛了一圈,发现 Nginx 有 keepconn 的设置,是代理模块用来保持源服务器连接的,一想 Apache 应该也有这个设置吧,难不成跟这个有关系?

于是找到 https://httpd.apache.org/docs/2.4/mod/mod_proxy.html,果然这设置讲究还挺多。大概看下来,这种服务器模式是代理模式,Apache 在这里开了个 ProcessPool,所以自然是可以控制池子的最小最大线程数,是否复用连接啥的。

  • min、max:连接池的上下限,能跟 PHP-fpm 的设置匹配自然是最好的
  • disablereuse、enablereuse:就跟 Nginx 的 keepconn 差不多的设置,Apache 默认是不会复用连接的,但对于繁忙站点来说,重复连接开销肯定比 reuse 大,所以需要手动打开复用
  • ttl:复用连接在 idle 状态下的最长时间秒数,默认是不启用。“Time to live for inactive connections and associated connection pool entries, in seconds. Once reaching this limit, a connection will not be used again; it will be closed at some later time.”

复用还是要开的,不过对于我这种强迫症来说,网站流量又小,一个复用连接开了几分钟都没用上,在 PHP-fpm 那里一直开着进程保持 reading headers 的监听状态,也浪费计算资源,还不如断了算了,自然是要配置 ttl 的。

最终 Apache 就配成了这个样子:

# Enable http authorization headers
 SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1

# Cause the PHP interpreter to handle files with a .php extension.
 <Proxy "unix:/var/run/php-fpm/www.sock|fcgi://php-fpm">
 ProxySet disablereuse=off connectiontimeout=3 timeout=300 ttl=30
 </Proxy>

# Redirect to the proxy
 <FilesMatch \.php$>
 <If "-f %{REQUEST_FILENAME}">
 SetHandler proxy:fcgi://php-fpm
 </If>
 </FilesMatch>

仔细一看,这里还可以跟 Nginx 一样有多 upstream 负载均衡、健康检测之类的玩法。单核小机就不玩这些了。

都平安夜了,为啥我还在干这些啊。

发表回复

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