一、worker process簡介
當我們談論到NGINX的高性能時,不得不提到它的多進程、多線程架構。其中,worker process是NGINX多進程架構的核心,它負責接受和處理客戶端的連接請求,並處理這些請求所需要的一系列操作。
在NGINX中,有一個master process和若干個worker process。其中master process主要負責初始化,然後fork出若干個worker process進行真正的請求處理。而每一個worker process都是獨立的進程,可以單獨對客戶端進行請求響應和處理。
master_process { // 初始化工作 ...... // fork出worker process進行請求處理 for (i = 0; i < worker_processes; i++) { spawn_worker_process(); } ...... } worker_process { // 處理請求 ...... }
二、worker process的創建和銷毀
正如上面的代碼所示,worker process是由master process通過fork創建的。每個worker process都是一個獨立的進程,有自己的進程ID以及內存空間。
當NGINX初始化完畢後,master process會根據預設的worker_process數量fork出若干個子進程,這些子進程就是我們常說的worker process。這些worker process會在某個事件被觸發時響應相應的事件,並進行處理。
在NGINX的運行過程中,有時候需要動態地增減worker process的數量。這時,master process會向已有的worker process發送信號,告訴它們需要創建新的worker process。而這些新的worker process則會在另一個進程空間中進行初始化和操作。
// master process發送信號給worker process,觸發創建新的worker process void ngx_signal_handler(int signo) { switch (signo) { case SIGHUP: ...... for (i = 0; i < ngx_worker_processes; i++) { ngx_pid = ngx_workers[i].pid; kill(ngx_pid, SIGQUIT); } ...... break; case SIGQUIT: ...... spawn_worker_process(); ...... break; ...... } }
三、worker process的事件處理
worker process作為NGINX的請求處理單元,是負責處理所有客戶端請求的進程。因此,worker process需要處理各種各樣的事件,包括網路連接事件、定時器事件、讀寫事件等。
在worker process的初始化過程中,會進行事件驅動機制的初始化。它會調用系統底層介面,比如epoll,select等,來監聽各種事件並進行處理。
// worker process初始化事件驅動機制 void ngx_worker_process_init_cycle() { ...... // 初始化epoll系統調用介面 ngx_epoll_init(cycle); ...... // 開始監聽事件 ngx_process_events_and_timers(cycle); ...... }
當worker process收到一個事件時,它會首先判斷這個事件的類型,然後根據不同的類型進行相應的處理。
// 處理網路連接事件 void ngx_event_accept(ngx_event_t *rev) { ...... } // 處理讀事件 void ngx_event_recv(ngx_event_t *ev, ngx_int_t flags) { ...... } // 處理定時器事件 void ngx_event_expire_timers() { ...... }
四、worker process的進程間通信
在NGINX的多進程架構中,worker process之間需要進行進程間通信,來共享一些資源或者協調某些操作。
這個進程間通信有多種方式,最常見的是信號和共享內存。
在我們剛才提到的動態增減worker process的情況下,master process會向所有已有的worker process發送SIGQUIT信號。這個信號的作用是使worker process進行優雅退出,釋放資源。當worker process處理完所有已有請求後退出時,master process會fork出新的worker process,以保證NGINX的運行穩定。
// 接收SIGQUIT信號進行退出 void ngx_worker_process_cycle() { ...... for (;;) { if (ngx_quit) { ngx_worker_process_exit(); } ...... } ...... }
除了信號外,共享內存也是worker process之間通信的常用方式。比如,當多個worker process都需要訪問共同的資源時,就可以使用共享內存。
// 在worker process中使用共享內存 void *ngx_shm_alloc(size_t size) { // 獲取共享內存 ngx_shm_info_t *shm_info = ngx_get_shm_info(); // 分配內存 void *addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, shm_info->fd, 0); ...... return addr; }
五、worker process的異常處理
在NGINX的運行過程中,worker process可能會因為一些異常情況而退出。比如,由於客戶端請求過多,導致worker process阻塞無法處理請求;或者是系統內存不足導致worker process無法運行。
當worker process退出時,master process會接收到這個信號,並重新創建新的worker process。同時,master process還會將進程退出的原因記錄在日誌中,以幫助管理員進行故障排查。
// worker process異常退出時記錄日誌 void ngx_process_get_status() { ...... if (WTERMSIG(status)) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "%P exited on signal %d", pid, WTERMSIG(status)); } else { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "%P exited with code %d", pid, WEXITSTATUS(status)); } ...... }
六、結語
本文深入探討了NGINX的worker process,希望能給大家提供一些關於NGINX多進程架構的實踐經驗。在NGINX的運行過程中,worker process起著至關重要的作用,因此我們需要深入理解它們的工作方式,以便在實踐中更好地調試和優化。
原創文章,作者:WCMGK,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/331769.html