前面我们说了,设置多个php-fpm进程池来分离网站。今天来聊聊多PHP-FPM主机。
您可能不知道APC或OPcache实际上是由PHP中的主进程持有的。APC的任何配置都需要来自.INI配置,以后不能通过ini_set()或php_admin_value覆盖。这是因为生成的PHP-FPM进程对APC缓存的大小或配置没有影响,因为它由主进程启动和管理。
这本质上意味着APC / OPcache缓存在所有PHP-FPM池之间共享。如果您只有一个网站可供服务,那就没问题了。如果您通过PHP-FPM在同一台服务器上有几十个站点,您应该知道它们都共享相同的APC / OPcache缓存。然后,APC或OPcache大小应该足够大,以保存所有站点的操作码缓存。
为避免这种情况,每个PHP-FPM池也可以单独启动并拥有自己的主进程。这意味着每个站点都可以拥有自己的APC或OPcache,并且可以独立于所有其他PHP-FPM池启动/停止。当需要激活新配置时,一个池配置的更改不会导致重新加载所有其他FPM池,这是“/etc/init.d/php-fpm reload”的默认行为(它将重新加载所有池)。
那么实现这一目标需要什么;
- 每个PHP-FPM池都需要自己的init.d启动/停止脚本
- 每个PHP-FPM池都需要自己的php-fpm.conf文件才能拥有唯一的PID
如果您通过CMS(例如Puppet / Chef / Salt / Ansible)管理您的环境,则上述设置并不困难。如果您手动执行操作,则可能会成为负担并且难以管理。
PHP-FPM配置
这是一个配置的例子。您现在将拥有一个.conf文件,其中包含主进程的配置(PID等)以及1个 PHP-FPM池的定义。
$ cat /etc/php-fpm.d/pool1.conf [global] pid = /var/run/php-fpm/pool1.pid log_level = notice emergency_restart_threshold = 0 emergency_restart_interval = 0 process_control_timeout = 0 daemonize = yes [pool1] listen = /var/run/php-fpm/pool1.sock listen.owner = pool1 listen.group = pool1 listen.mode = 0666 user = pool1 group = pool1 pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 10s pm.max_requests = 500
以上包含最重要的信息; 主配置确定它可以进行守护化, 并且 pid 文件应该位于何处。池配置具有要侦听的位置和进程管理器的类型的基本信息。
init.d文件是默认的/etc/init.d/php-fpm的简单复制/粘贴,只有一些修改。
$ cat /etc/init.d/php-fpm-pool1 #! /bin/sh # # chkconfig: - 84 16 # description: PHP FastCGI Process Manager for pool 'pool1' # processname: php-fpm-pool1 # config: /etc/php-fpm.d/pool1.conf # pidfile: /var/run/php-fpm/pool1.pid # Standard LSB functions #. /lib/lsb/init-functions # Source function library. . /etc/init.d/functions # Check that networking is up. . /etc/sysconfig/network if [ "$NETWORKING" = "no" ] then exit 0 fi RETVAL=0 prog="php-fpm-pool1" pidfile=/var/run/php-fpm/pool1.pid lockfile=/var/lock/subsys/php-fpm-pool1 fpmconfig=/etc/php-fpm.d/pool1 start () { echo -n $"Starting $prog: " daemon --pidfile ${pidfile} php-fpm --fpm-config=${fpmconfig} --daemonize RETVAL=$? echo [ $RETVAL -eq 0 ] && touch ${lockfile} } stop () { echo -n $"Stopping $prog: " killproc -p ${pidfile} php-fpm RETVAL=$? echo if [ $RETVAL -eq 0 ] ; then rm -f ${lockfile} ${pidfile} fi } restart () { stop start } reload () { echo -n $"Reloading $prog: " killproc -p ${pidfile} php-fpm -USR2 RETVAL=$? echo } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) status -p ${pidfile} php-fpm RETVAL=$? ;; restart) restart ;; reload|force-reload) reload ;; condrestart|try-restart) [ -f ${lockfile} ] && restart || : ;; *) echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|try-restart}" RETVAL=2 ;; esac exit $RETVAL
我们更改init.d脚本的唯一部分位于顶部; 已定义新的进程名称(这要求是唯一的),并且PID文件已更改为指向此池的自定义PID文件,因为它在上面的pool1.conf文件中定义。
您现在可以与其他所有池分开启动/停止此池。它的配置可以在不影响其他配置的情况下进行更改。如果您配置了多个池,则您的进程列表将如下所示。
root 5963 4704 ? Ss 19:23 0:00 php-fpm: master process (/etc/php-fpm.d/pool1.conf) root 6036 4744 ? Ss 19:23 0:00 php-fpm: master process (/etc/php-fpm.d/pool2.conf) 多个主进程以root身份运行,并且正在侦听池配置中定义的套接字。一旦发出PHP请求,它们就会产生子进程来处理它们并在10次空闲后再次停止它们。 主进程还会显示它加载的配置文件,从而可以轻松查明该特定池的配置。
更好的分离
一旦发出PHP请求,进程列表就像这样。
root 5963 4704 Ss 19:23 php-fpm: master process (/etc/php-fpm.d/p1.conf) user 3987 4504 S 19:23 \_ php-fpm: pool pool1 user 3987 4504 S 19:23 \_ php-fpm: pool pool1 root 6036 4744 Ss 19:23 php-fpm: master process (/etc/php-fpm.d/p2.conf) user 3987 4504 S 19:23 \_ php-fpm: pool pool2
总而言之,以上有两个主要优点:
- 每个PHP-FPM池享有单独的APC / OPcache字节码缓存
- 能够在不影响其他已定义池的情况下启动/停止/重新配置PHP-FPM池
这对于在PHP部署中遇到APC / OPcache / realpath / stat缓存问题的任何人来说,这种配置可以通过允许(sudo)访问重新启动或重新加载特定池的主PHP-FPM进程来清除所有缓存。
这样做时要记住的事情:
- 如果在每个FPM池中使用错误日志记录,则应修改Logrotate,以使用正确的池的PID重新加载主进程;
- 确保所有FPM池都在系统引导时启动,因为它们每个都有一个新的init.d脚本(通过chkconfig --list检查);
本文地址 http://blog.p2hp.com/archives/5814,转载请注明来自Lenix的博客,谢谢。