一次線上問題,讓我意識到,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架構師下載