一次线上问题,让我意识到,fpm 竟然是用这种方式处理超时的,虽然有点震惊,可是想一想,这才是我大 PHP 处理问题的方式,简单粗暴并且高效。api
问题的现象是这样的,某个接口访问量大增,而后接口大量502,接着 fpm 的机器cpu暴涨,最后gg。架构
fpm 处理超时的方式很是简单,那就是,直接退出 worker 子进程。code
对于超时的处理,fpm 的代码里是这样写的的(我隐去了细节,有兴趣的能够去 PHP 官网下载一份源码看看,在源码的 sapi/fpm 目录里) 检测超时接口
static void fpm_pctl_check_request_timeout(struct timeval *now) { …… fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout); …… }
处理超时进程
void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout) { …… fpm_pctl_kill(child->pid, FPM_PCTL_TERM); …… } }
而后kill源码
int fpm_pctl_kill(pid_t pid, int how) { …… return kill(pid, s); }
而后问题就清楚了,接口里有个服务超时,形成fpm超时,fpm worker 进程不断被kill掉并拉起新的 fpm worker 进程,而后不断的这样 kill 而后拉起,cpu 就暴涨,最后 gg。技巧
这个问题怎么避免,去掉 fpm 超时是万万不可取的,只能严格控制代码,调用每个外部服务必须设置超时时间,并且这个超时时间必须小于 fpm 超时时间。request
更多架构、PHP、GO相关踩坑实践技巧请关注个人公众号:PHP架构师下载