?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
請求處理
fpm_run()執(zhí)行后將fork出worker進(jìn)程,worker進(jìn)程返回main()中繼續(xù)向下執(zhí)行,后面的流程就是worker進(jìn)程不斷accept請求,然后執(zhí)行PHP腳本并返回。整體流程如下:
(1)等待請求: worker進(jìn)程阻塞在fcgi_accept_request()等待請求;
(2)解析請求: fastcgi請求到達(dá)后被worker接收,然后開始接收并解析請求數(shù)據(jù),直到request數(shù)據(jù)完全到達(dá);
(3)請求初始化: 執(zhí)行php_request_startup(),此階段會調(diào)用每個擴(kuò)展的:PHP_RINIT_FUNCTION();
(4)編譯、執(zhí)行: 由php_execute_script()完成PHP腳本的編譯、執(zhí)行;
(5)關(guān)閉請求: 請求完成后執(zhí)行php_request_shutdown(),此階段會調(diào)用每個擴(kuò)展的:PHP_RSHUTDOWN_FUNCTION(),然后進(jìn)入步驟(1)等待下一個請求。
int main(int argc, char *argv[]){ ... fcgi_fd = fpm_run(&max_requests); parent = 0; //初始化fastcgi請求 request = fpm_init_request(fcgi_fd); //worker進(jìn)程將阻塞在這,等待請求 while (EXPECTED(fcgi_accept_request(request) >= 0)) { SG(server_context) = (void *) request; init_request_info(); //請求開始 if (UNEXPECTED(php_request_startup() == FAILURE)) { ... } ... fpm_request_executing(); //編譯、執(zhí)行PHP腳本 php_execute_script(&file_handle); ... //請求結(jié)束 php_request_shutdown((void *) 0); ... } ... //worker進(jìn)程退出 php_module_shutdown(); ... }
worker進(jìn)程一次請求的處理被劃分為5個階段:
FPM_REQUEST_ACCEPTING: 等待請求階段
FPM_REQUEST_READING_HEADERS: 讀取fastcgi請求header階段
FPM_REQUEST_INFO: 獲取請求信息階段,此階段是將請求的method、query stirng、request uri等信息保存到各worker進(jìn)程的fpm_scoreboard_proc_s結(jié)構(gòu)中,此操作需要加鎖,因為master進(jìn)程也會操作此結(jié)構(gòu)
FPM_REQUEST_EXECUTING: 執(zhí)行請求階段
FPM_REQUEST_END: 沒有使用
FPM_REQUEST_FINISHED: 請求處理完成
worker處理到各個階段時將會把當(dāng)前階段更新到fpm_scoreboard_proc_s->request_stage,master進(jìn)程正是通過這個標(biāo)識判斷worker進(jìn)程是否空閑的。