天天看點

三:深入了解Nginx的子產品化 (結合源碼詳解)worker程序工作流程master程序工作流程

盜用前面用到的流程圖

三:深入了解Nginx的子產品化 (結合源碼詳解)worker程式工作流程master程式工作流程
第二步實際上是調用

ngx_add_inherited_sockets()

//檔案名: Nginx.c

int ngx_cdecl
main(int argc, char *const *argv)
{
 ...

    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return ;
    }

 ...
}
           
Nginx在不重新開機服務更新,舊版本的

master

程序會通過

execve

系統調用來啟動新版本的

master

程序(先 fork()出子程序再調用exec來運作新程式),這時舊版本 的

master

程序通過 環境變量通知新版本的

master

這是在更新,新版本的

master

程序通過

ngx_add_inherited_sockets()

方法 由環境變量裡讀取平滑更新資訊,并對舊版本Nginx服務監聽 的句柄做繼承處理 。
3~8步都在

ngx_init_cycle()

方法中執行的。在初始化

ngx_cycle_t

中所有的容器後,會為讀取、解析檔案 做準備工作。因為每個 子產品都必須有相應的資料結構來 存儲配置檔案中的各配置項,建立這些資料結構的工作都需要在這一步進行。Nginx架構隻關心

NGX_CORE_MODULE

核心子產品,進而降低架構的複雜度,這裡将會調用所有核心子產品的

create_conf

的方法(也隻有核心子產品才有這個方法 ),這意味着所有核心子產品開始構造用于存儲配置項的結構體。非核心子產品将由每個子產品進行管理,如 HTTP子產品都由

ngx_http_module

管理。這樣

ngx_http_module

在解析自己感興趣的”http”配置項時,将會調用所有HTTP子產品 約定的方法來 建立存儲配置的結構體
//檔案名 ngx_cycle.h
typedef struct ngx_cycle_s       ngx_cycle_t;
struct ngx_cycle_s {
    void                  ****conf_ctx;                       // 配置上下文數組(含所有子產品)
    ngx_pool_t               *pool;                           // 記憶體池

    ngx_log_t                *log;                            // 日志
    ngx_log_t                 new_log;

    ngx_connection_t        **files;                         // 連接配接檔案
    ngx_connection_t         *free_connections;              // 空閑連接配接
    ngx_uint_t                free_connection_n;             // 空閑連接配接個數
    ngx_module_t            **modules;
    ngx_uint_t                modules_n;
    ngx_uint_t                modules_used;    /* unsigned  modules_used:1; */
    ngx_queue_t               reusable_connections_queue;    // 再利用連接配接隊列

    ngx_array_t               listening;                     // 監聽套接字數組
    ngx_array_t               pathes;                        // 路徑數組
    ngx_list_t                open_files;                    // 打開檔案連結清單
    ngx_list_t                shared_memory;                 // 共享記憶體連結清單

    ngx_uint_t                connection_n;                  // 連接配接個數
    ngx_uint_t                files_n;                       // 打開檔案個數

    ngx_connection_t         *connections;                   // 連接配接
    ngx_event_t              *read_events;                   // 讀事件
    ngx_event_t              *write_events;                  // 寫事件

    ngx_cycle_t              *old_cycle;                     // old cycle指針

    ngx_str_t                 conf_file;                     // 配置檔案
    ngx_str_t                 conf_param;                    // 配置參數
    ngx_str_t                 conf_prefix;                   // 配置檔案目錄
    ngx_str_t                 prefix;                        // 程式工作目錄
    ngx_str_t                 lock_file;                     // 鎖檔案,用在不支援accept_mutex的系統中
    ngx_str_t                 hostname;                      // 主機名
};
           
調用配置子產品提供的解析配置項方法 。周遊

nginx.conf

的所有配置項,對于任一配置項,将會檢查所有核心子產品以找出對它所感興趣的子產品。并調用該子產品在

ngx_command_t

結構體中的定義的 配置項處理辦法 。

調用所有的

NGX_CORE_MODULE

核心子產品的

init_conf

的 方法。這一步驟的 目的在于讓所有核心子產品在解析完配置項可以做綜合性處理。

之前第四步在 解析配置項時,所有的子產品都已經解析出自己需要監聽的端口 ,如HTTP子產品 已經 在 解析http{…}配置項時得到要監聽的端口 ,并添加到listening數組中。這一步驟就是按照listening數組中的每一個

ngx_listening_t

元素設定socket句柄并監聽端口,實際上就是調用

ngx_open_listening_sockets()

在這個階段會調用所有子產品的

init_module

方法。接下來 就是根據 配置Nginx運作模式決定如何工作。

接下來流程可以參考之前的部落格nginx代碼分析

worker程序工作流程

master

采用的是信号的方式通知worker程序停止服務或更換日志。在函數

ngx_worker_process_cycle()

通過檢查

ngx_exiting、ngx_terminate、ngx_quit、ngx_reopen

這4個标志位來決定後續動作。

三:深入了解Nginx的子產品化 (結合源碼詳解)worker程式工作流程master程式工作流程

master程序工作流程

master

程序不需要處理網絡事件,不負責業務的執行,隻會通過該管理

worker

等子程序來實作重新開機服務、平滑更新、更換日志檔案、配置檔案實時生效等 功能 。

master

程序中所有子程序相關的狀态資訊都儲存在ngx_processes數組中,下面 是數組元素的類型

ngx_process_t

的 結構的定義,代碼如下 :

typedef struct {
    //程序 ID
    ngx_pid_t           pid;
    // 由waitpid系統調用擷取到程序狀态
    int                 status;
    // 這是由socketpair系統調用産生出用于程序 間通信 的socket句柄
    ngx_socket_t        channel[];
    // 子程序的循環執行的辦法,當父程序調用ngx_spawn_process  生成子程序時使用
    ngx_spawn_proc_pt   proc;
    void               *data;
    // 程序名稱。作業系統中顯示的程序名稱與name相同
    char               *name;
    // 标志位,為1時表示在重新生成子程序
    unsigned            respawn:;
    // 标志位, 為1時表示正在 生成子程序
    unsigned            just_spawn:;
    // 标志位,為1時表示在父程序、子程序分離
    unsigned            detached:;
    // 标志位,為1時表示程序正在退出
    unsigned            exiting:;
    // 标志位,為1時表示程序已經退出
    unsigned            exited:;
} ngx_process_t;
           

ngx_spawn_process

方法封裝了

fork

系統調用,并且會從

ngx_processes

數組中選擇一個還未使用的

ngx_process_t

元素存儲這個子程序的相關資訊。
三:深入了解Nginx的子產品化 (結合源碼詳解)worker程式工作流程master程式工作流程

繼續閱讀