天天看點

《深入了解Nginx:子產品開發與架構解析》一3.3 如何将自己的HTTP子產品編譯進Nginx

nginx提供了一種簡單的方式将第三方的子產品編譯到nginx中。首先把源代碼檔案全部放到一個目錄下,同時在該目錄中編寫一個檔案用于通知nginx如何編譯本子產品,這個檔案名必須為config。它的格式将在3.3.1節中說明。

這樣,隻要在configure腳本執行時加入參數--add-module=path(path就是上面我們給定的源代碼、config檔案的儲存目錄),就可以在執行正常編譯安裝流程時完成nginx編譯工作。

有時,nginx提供的這種方式可能無法滿足我們的需求,其實,在執行完configure腳本後nginx會生成objs/makefile和objs/ngx_modules.c檔案,完全可以自己去修改這兩個檔案,這是一種更強大也複雜得多的方法,我們将在3.3.3節中說明如何直接修改它們。

config檔案其實是一個可執行的shell腳本。如果隻想開發一個http子產品,那麼config檔案中需要定義以下3個變量:

ngx_addon_name:僅在configure執行時使用,一般設定為子產品名稱。

http_modules:儲存所有的http子產品名稱,每個http子產品間由空格符相連。在重新設定http_modules變量時,不要直接覆寫它,因為configure調用到自定義的config腳本前,已經将各個http子產品設定到http_modules 變量中了,是以,要像如下這樣設定:

ngx_addon_srcs:用于指定新增子產品的源代碼,多個待編譯的源代碼間以空格符相連。注意,在設定ngx_addon_srcs時可以使用$ngx_addon_dir變量,它等價于configure執行時--add-module=path的path參數。

是以,對于mytest子產品,可以這樣編寫config檔案:

注意 以上3個變量并不是唯一可以在config檔案中自定義的部分。如果我們不是開發http子產品,而是開發一個http過濾子產品,那麼就要用http_filter_modules替代上面的http_modules變量。事實上,包括$core_modules、$event_modules、$http_modules、 $http_filter_modules、$http_headers_filter_module等子產品變量都可以重定義,它們分别對應着nginx的核心子產品、事件子產品、http子產品、http過濾子產品、http頭部過濾子產品。除了ngx_addon_srcs變量,或許還有一個變量我們會用到,即$ngx_addon_deps變量,它指定了子產品依賴的路徑,同樣可以在config中設定。

在1.6節提到的configure執行流程中,其中有兩行腳本負責将第三方子產品加入到nginx中,如下所示。

下面完整地解釋一下configure腳本是如何與3.3.1節中提到的config檔案配合起來把定制的第三方子產品加入到nginx中的。

在執行configure --add-module=path指令時,path就是第三方子產品所在的路徑。在configure中,通過auto/options腳本設定了ngx_addons變量:

在configure指令執行到auto/modules腳本時,将在生成的ngx_modules.c檔案中加入定制的第三方子產品。

可以看到,$ngx_addons可以包含多個目錄,對于每個目錄,如果其中存在config檔案就會執行,也就是說,在config中重新定義的變量都會生效。之後,auto/modules腳本開始建立ngx_modules.c檔案,這個檔案的關鍵點就是定義了ngx_module_t *ngx_modules[]數組,這個數組存儲了nginx中的所有子產品。nginx在初始化、處理請求時,都會循環通路ngx_modules數組,确定該用哪一個子產品來處理。下面來看一下auto/modules是如何生成數組的,代碼如下所示:

首先,auto/modules會按順序生成modules變量。注意,這裡的$http_modules等已經在config檔案中重定義了。這時,modules變量是包含所有子產品的。然後,開始生成ngx_modules.c檔案:

這樣就已經确定了nginx在運作時會調用自定義的子產品,而auto/make腳本負責把相關子產品編譯進nginx。

在makefile中生成編譯第三方子產品的源代碼如下:

下面這段代碼用于将各個子產品的目标檔案設定到ngx_obj變量中,緊接着會生成makefile裡的連結代碼,并将所有的目标檔案、庫檔案連結成二進制程式。

綜上可知,第三方子產品就是這樣嵌入到nginx程式中的。

3.3.2節中介紹的方法毫無疑問是最友善的,因為大量的工作已由nginx中的configure腳本幫我們做好了。在使用其他第三方子產品時,一般也推薦使用該方法。

我們有時可能需要更靈活的方式,比如重新決定ngx_module_t *ngx_modules[]數組中各個子產品的順序,或者在編譯源代碼時需要加入一些獨特的編譯選項,那麼可以在執行完configure後,對生成的objs/ngx_modules.c和objs/makefile檔案直接進行修改。

在修改objs/ngx_modules.c時,首先要添加新增的第三方子產品的聲明,如下所示。

其次,在合适的地方将子產品加入到ngx_modules數組中。

注意,子產品的順序很重要。如果同時有兩個子產品表示對同一個請求感興趣,那麼隻有順序在前的子產品會被調用。

修改objs/makefile時需要增加編譯源代碼的部分,例如:

還需要把目标檔案連結到nginx中,例如:

請慎用這種直接修改makefile和ngx_modules.c的方法,不正确的修改可能導緻nginx工作不正常。

繼續閱讀