http://tonybai.com/2017/01/17/understanding-flannel-network-for-kubernetes/
讲的不错(记得架梯)
DevOps
问题:
如何让php-fpm能优雅地重启?
办法:
问题:
kill -SIGQUIT 可以解除子进程对9000端口的listen,却不能解除master进程对9000端口的listen
子进程的listen是继承父进程的
子进程接到SIGQUIT 信号后,close掉listen的文件描述符,然后创建了一个新的socket,如下:
(为什么要创建一个新的socket?)
同一个文件描述符被fork到多个子进程后,每个进程的关闭只会在本进程内关闭(让该资源和本进程脱离关系),然后减少该资源的引用计数,直到最后一个引用被解除,该资源才真正销毁
关于上述的问题7:
1 2 3 4 5 6 7 8 9 |
<?php $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to ); $process = proc_open('sleep 10000',$descriptorspec, $pipe); print_r($pipe); sleep(10000); |
这样就对了; 而且,proc_close() 可以获取外部进程的退出码
1 2 3 |
#!/bin/bash exec 0<&- $@ |
注意: 这个shell会存在一些问题,如下:
改进如下:
1 2 3 4 5 |
#!/bin/bash exec 0<&- cmd=$1 shift $cmd "$@" |
到现在为止,我们有能力不让外部的子进程来影响fpm请求的处理了;但是,还有一个listen 9000 但是不能处理请求的进程,那就是: php-fpm master进程
我们的处理方法可以如下:
最后:
我们还没有解决如何让旧进程消费完旧进程的backlog中剩余的连接的问题,稍后研究。
分析:
socket中有一个shutdown的方法,可以关闭socket的读或(和)写,会触发关闭已建立的连接的方法,(对于listen的socket没有对端,想必不能用shutdown方法),测试发现:
1 2 3 4 5 |
<?php $s = socket_create_listen (8882, 1); fgets(STDIN); socket_shutdown($s); fgets(STDIN); |
一种其它的实现方式:
在so_reuseport出现之前(包括现在)有一些程序是可以实现优雅重启的,原理就是,新旧进程时间继承lisen的文件描述符; 其实,继承文件描述符需要不小的工作量的。
如果能有一种标准的接口来处理继承文件描述符的事情,那么完全可以开发一个和应用无关的小程序,用来创建socket端口,然后遗传给真正要干活的应用程序,只需要遗传给应用程序的master进程就算OK了,如果需要重启程序,则只需要fork新的应用程序的master进程,然后发信号让旧的空闲的应用进程退出就可以了,这样就不会丢弃已创建的连接。
参考:
https://my.oschina.net/miffa/blog/390931