平滑重启之php-fpm

2,396 阅读3分钟

       众所周知php是动态型语言,在每次处理请求时都是临时进行代码的编译执行所以对于这种语言在上线时是不需要重启的,直接采用文件覆盖的方式进行或者采用软链的方式进行替换也可以,由于这种特性使得其性能经常被人诟病,所以就有了php-fpm这种进程管理工具来配合其使用,使得如今php-fpm成为了php的标配(apache就不是利用这种的),但是php-fpm是用c编写的,c是静态型语言,所以在修改php-fpm的配置时还是需要重启的(不过这种情况一帮很少见),那么在需要重启时php-fpm又是如何运作的呢? 下面来讲讲。

     在平滑重启时需要考虑的问题一般有两方面:一方面,未结束的请求如何处理,另一方面,进程处理时间过长如何处理。对于这两个方面,php-fpm都给出了自己的解决方法,这两方面是相互进行的,不是独立的。

    注意:给php-fpm发送重启信号kill -USR2 pid  这个pid既可以是master进程的pid,也可以是worker进程的pid,如果是master进程的pid就会吧所有worker进程重启,如果是worker进程的pid就是只重启当个worker进程。

     未结束的请求如何处理:

           发送重启信号是会通知master,master获取event然后给worker进程发送退出的信号SIGQUIT,worker进程接收信号后交给对应的信号处理函数处理,信号函数就是将in_shutdown变量置为1,这样worker进程 在调用fcgi_accept_request进程下一个进程处理时就不接收直接退出了,(注意这里也会有处理时间过长问题),如果进程还没有执行结束也会退出,这样就会出现代码逻辑执行一半的情况,所以要特别注意。从这里可以看出来php-fpm的重启逻辑简单粗暴,(在规定时间内处理完请求,完成不了就不管了),由于php-fpm一个worker进程每次只能处理一个请求,所以不需要计数器之类的,这样就更简单了。

     处理时间过长如何处理:

          在给php-fpm进程发送信号时,php-fpm进程就会重启操作流程,在整个重启操作流程当中为了保证顺利的重启增加了超时机制,超过了设置的时间就会强制重启,中断正在进行中的进程。这个配置是在php-fpm.ini文件中设置的,process_control_timeout=10 这个字段就是用来设置的,表示最多10秒。

  实例:      

          代码测试,在设置10秒超时情况下,代码逻辑需要11秒的情况下,重启会造成代码执行部分然后退出的情况。

    public function actionTest(){     
      $model = new bad(); 
      $model->save(array('id'=>75329370));
      //需要特别注意不能使用sleep方法进行时间的等待,
      //因为是调用系统的sleep方法,在重启时会使其失效    
      $model->db()->query('select sleep(11) from orders where id=75329370');                                                                                                            
       $model2 = new lock();
        $model2->save(array('id'=>10251,'info'=>1212));  
       return; 
   }