nginx建立和監聽套接字分析

曉鎂發表於2020-12-13

簡介

nginx作為一個web伺服器,肯定是有listen套接字對外提供服務的,listen套接字是用於接收HTTP請求。

nginx監聽套接字的建立是根據配置檔案的內容來建立的,在nginx.conf檔案中有多少個地址就需要建立多少個監聽套接字。

本文不針對原始碼逐一註解分析,只是說明套接字建立監聽流程。

流程

當客戶端發來http請求與服務端建立一個連線,過程如下:

    1.nginx首先在main函式中呼叫了ngx_init_cycle()函式,在這個函式的最後呼叫了ngx_open_listening_sockets函式,這個函式負責將建立的監聽套接字進行套接字選項的設定(比如非阻塞、接受傳送的緩衝區、繫結、監聽處理)。

    2.nginx建立套接字是在哪裡呢?在解析http{}配置的時候,也就是在ngx_http_block()函式內,在這個函式的最後呼叫ngx_http_optimize_servers()函式。
    在這個函式內最後呼叫了ngx_http_init_listening()函式,這個函式呼叫了ngx_http_add_listening函式,在這個函式總呼叫了ngx_create_listening()函式。

    這個函式根據每一個IP地址:port這種配置建立一個監聽套接字,這個函式還有一個很重要的任務,就是將監聽套接字的回撥函式設定為ngx_http_init_connection函式,記住這是監聽套接字上的回撥,而不是監聽套接字對應的可讀事件的回撥函式。

    3.nginx什麼時候接受客戶端http請求建立的連線呢?在ngx_event_process_init()函式內,這個函式是作為ngx_event_core_module模組建立的init_process函式。

    這個函式是在worker程式初始化是被被呼叫的,ngx_event_process_init函式將每個監聽套接字和一個連線(ngx_connection_t)相互建立關係。

    在cycle內建立一個連線池,建立一個讀事件池,建立一個寫事件的池,然後建立for迴圈遍歷cycle中的所有ngx_listening_t的結構體,對每一個ngx_listening_t結構體,也就是每一個監聽套接字,從連線池中獲取一個連線,將這個連線對應這個監聽套接字,然後將讀事件設定為ngx_event_accept,那麼在對應的監聽套接字上accept接受新的連線(劃重點)!!!

    4.連線結束完成後,呼叫這個監聽套接字上的handler,也就是ngx_http_init_connection函式,從這個函式開始了HTTP請求的互動!

總結

首先對於一個初始化好的ngx_listening_t時,這裡面只有一個套接字,沒有可讀可寫事件,它需要ngx_connection_t託管,在ngx_connection_t中可讀可寫事件,在ngx_event_t結構中,data對應一個ngx_connection_t結構體。

相關文章