.
├── auto 自動檢測系統環境以及編譯相關的腳本
│ ├── cc 關於編譯器相關的編譯選項的檢測腳本
│ ├── lib nginx編譯所須要的一些庫的檢測腳本
│ ├── os 與平臺相關的一些系統參數與系統調用相關的檢測
│ └── types 與數據類型相關的一些輔助腳本
├── conf 存放默認配置文件,在make install後,會拷貝到安裝目錄中去
├── contrib 存放一些實用工具,如geo配置生成工具(geo2nginx.pl)
├── html 存放默認的網頁文件,在make install後,會拷貝到安裝目錄中去
├── man nginx的man手冊
└── src 存放nginx的源代碼
├── core nginx的核心源代碼,包括經常使用數據結構的定義,以及nginx初始化運行的核心代碼如main函數
├── event 對系統事件處理機制的封裝,以及定時器的實現相關代碼
│ └── modules 不一樣事件處理方式的模塊化,如select、poll、epoll、kqueue等
├── http nginx做爲http服務器相關的代碼
│ └── modules 包含http的各類功能模塊
├── mail nginx做爲郵件代理服務器相關的代碼
├── misc 一些輔助代碼,測試c++頭的兼容性,以及對google_perftools的支持
└── os 主要是對各類不一樣體系統結構所提供的系統函數的封裝,對外提供統一的系統調用接口
nginx的編譯旅程將從configure開始,configure腳本將根據咱們輸入的選項、系統環境參與來生成所需的文件(包含源文件與Makefile文件)。configure會調用一系列auto腳原本實現編譯環境的初始化。html
auto腳本由一系列腳本組成,他們有一些是實現一些通用功能由其它腳原本調用(如have),有一些則是完成一些特定的功能(如option)。腳本之間的主要執行順序及調用關係以下圖所示(由上到下,表示主流程的執行):python
接下來,咱們結合代碼來分析下configure的原理:nginx
. auto/options
. auto/init
. auto/sources
這是configure源碼開始執行的前三行,依次交由auto目錄下面的option、init、sources來處理。c++
##1. 設置選項對應的shell變量以及他們的初始值
help=no
NGX_PREFIX=
NGX_SBIN_PATH=
NGX_CONF_PREFIX=
NGX_CONF_PATH=
NGX_ERROR_LOG_PATH=
NGX_PID_PATH=
NGX_LOCK_PATH=
NGX_USER=
NGX_GROUP=
...
## 2, 處理每個選項值,並設置到對應的全局變量中
for option
do
opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"
# 獲得此選項的value部分
case "$option" in
-*=*) value=`echo "$option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
# 根據option內容進行匹配,並設置相應的選項
case "$option" in
--help) help=yes ;;
--prefix=) NGX_PREFIX="!" ;;
--prefix=*) NGX_PREFIX="$value" ;;
--sbin-path=*) NGX_SBIN_PATH="$value" ;;
--conf-path=*) NGX_CONF_PATH="$value" ;;
--error-log-path=*) NGX_ERROR_LOG_PATH="$value";;
--pid-path=*) NGX_PID_PATH="$value" ;;
--lock-path=*) NGX_LOCK_PATH="$value" ;;
--user=*) NGX_USER="$value" ;;
--group=*) NGX_GROUP="$value" ;;
...
*)
# 沒有找到的對應選項
echo "$0: error: invalid option \"$option\""
exit 1
;;
esac
done
## 3. 對選項進行處理
# 若是有--help,則輸出幫助信息
if [ $help = yes ]; then
cat << END
--help print this message
--prefix=PATH set installation prefix
--sbin-path=PATH set nginx binary pathname
--conf-path=PATH set nginx.conf pathname
--error-log-path=PATH set error log pathname
--pid-path=PATH set nginx.pid pathname
--lock-path=PATH set nginx.lock pathname
--user=USER set non-privileged user for
worker processes
--group=GROUP set non-privileged group for
worker processes
END
exit 1
fi
# 默認文件路徑
NGX_CONF_PATH=${NGX_CONF_PATH:-conf/nginx.conf}
NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH`
NGX_PID_PATH=${NGX_PID_PATH:-logs/nginx.pid}
NGX_LOCK_PATH=${NGX_LOCK_PATH:-logs/nginx.lock}
...
上面的代碼中,咱們選用了文件中的部分代碼進行了說明。你們可結合源碼再進行分析。auto/options的目的主要是處理用戶選項,並由選項生成一些全局變量的值,這些值在其它文件中會用到。該文件也會輸出configure的幫助信息。shell
該文件的目錄在於初始化一些臨時文件的路徑,檢查echo的兼容性,並建立Makefile。服務器
# 生成最終執行編譯的makefile文件路徑
NGX_MAKEFILE=$NGX_OBJS/Makefile
# 動態生成nginx模塊列表的路徑,因爲nginx的的一些模塊是能夠選擇編譯的,並且能夠添加本身的模塊,因此模塊列表是動態生成的
NGX_MODULES_C=$NGX_OBJS/ngx_modules.c
NGX_AUTO_HEADERS_H=$NGX_OBJS/ngx_auto_headers.h
NGX_AUTO_CONFIG_H=$NGX_OBJS/ngx_auto_config.h
# 自動測試目錄與日誌輸出文件
NGX_AUTOTEST=$NGX_OBJS/autotest
# 若是configure出錯,可用來查找出錯的緣由
NGX_AUTOCONF_ERR=$NGX_OBJS/autoconf.err
NGX_ERR=$NGX_OBJS/autoconf.err
MAKEFILE=$NGX_OBJS/Makefile
NGX_PCH=
NGX_USE_PCH=
# 檢查echo是否支持-n或\c
# check the echo's "-n" option and "\c" capability
if echo "test\c" | grep c >/dev/null; then
# 不支持-c的方式,檢查是否支持-n的方式
if echo -n test | grep n >/dev/null; then
ngx_n=
ngx_c=
else
ngx_n=-n
ngx_c=
fi
else
ngx_n=
ngx_c='\c'
fi
# 建立最初始的makefile文件
# default表示目前編譯對象
# clean表示執行clean工做時,須要刪除makefile文件以及objs目錄
# 整個過程當中只會生成makefile文件以及objs目錄,其它全部臨時文件都在objs目錄之下,因此執行clean後,整個目錄還原到初始狀態
# 要再次執行編譯,須要從新執行configure命令
# create Makefile
cat << END > Makefile
default: build
clean:
rm -rf Makefile $NGX_OBJS
END
該文件從文件名中就能夠看出,它的主要功能是跟源文件相關的。它的主要做用是定義不一樣功能或系統所須要的文件的變量。根據功能,分爲CORE/REGEX/EVENT/UNIX/FREEBSD/HTTP等。每個功能將會由四個變量組成,」_MODULES」表示此功能相關的模塊,最終會輸出到ngx_modules.c文件中,即動態生成須要編譯到nginx中的模塊;」INCS」表示此功能依賴的源碼目錄,查找頭文件的時候會用到,在編譯選項中,會出如今」-I」中;」DEPS」顯示指明在Makefile中須要依賴的文件名,即編譯時,須要檢查這些文件的更新時間;」SRCS」表示須要此功能編譯須要的源文件。數據結構
拿core來講:memcached
CORE_MODULES="ngx_core_module ngx_errlog_module ngx_conf_module ngx_emp_server_module ngx_emp_server_core_module" CORE_INCS="src/core" CORE_DEPS="src/core/nginx.h \ src/core/ngx_config.h \ src/core/ngx_core.h \ src/core/ngx_log.h \ src/core/ngx_palloc.h \ src/core/ngx_array.h \ src/core/ngx_list.h \ src/core/ngx_hash.h \ src/core/ngx_buf.h \ src/core/ngx_queue.h \ src/core/ngx_string.h \ src/core/ngx_parse.h \ src/core/ngx_inet.h \ src/core/ngx_file.h \ src/core/ngx_crc.h \ src/core/ngx_crc32.h \ src/core/ngx_murmurhash.h \ src/core/ngx_md5.h \ src/core/ngx_sha1.h \ src/core/ngx_rbtree.h \ src/core/ngx_radix_tree.h \ src/core/ngx_slab.h \ src/core/ngx_times.h \ src/core/ngx_shmtx.h \ src/core/ngx_connection.h \ src/core/ngx_cycle.h \ src/core/ngx_conf_file.h \ src/core/ngx_resolver.h \ src/core/ngx_open_file_cache.h \ src/core/nginx_emp_server.h \ src/core/emp_server.h \ src/core/task_thread.h \ src/core/standard.h \ src/core/dprint.h \ src/core/ngx_crypt.h" CORE_SRCS="src/core/nginx.c \ src/core/ngx_log.c \ src/core/ngx_palloc.c \ src/core/ngx_array.c \ src/core/ngx_list.c \ src/core/ngx_hash.c \ src/core/ngx_buf.c \ src/core/ngx_queue.c \ src/core/ngx_output_chain.c \ src/core/ngx_string.c \ src/core/ngx_parse.c \ src/core/ngx_inet.c \ src/core/ngx_file.c \ src/core/ngx_crc32.c \ src/core/ngx_murmurhash.c \ src/core/ngx_md5.c \ src/core/ngx_rbtree.c \ src/core/ngx_radix_tree.c \ src/core/ngx_slab.c \ src/core/ngx_times.c \ src/core/ngx_shmtx.c \ src/core/ngx_connection.c \ src/core/ngx_cycle.c \ src/core/ngx_spinlock.c \ src/core/ngx_cpuinfo.c \ src/core/ngx_conf_file.c \ src/core/ngx_resolver.c \ src/core/ngx_open_file_cache.c \ src/core/nginx_emp_server.c \ src/core/emp_server.c \ src/core/standard.c \ src/core/task_thread.c \ src/core/dprint.c \ src/core/ngx_crypt.c"
若是咱們本身寫一個第三方模塊,咱們可能會引用到這些變量的值,或對這些變量進行修改,好比添加咱們本身的模塊,或添加本身的一個頭文件查找目錄(在第三方模塊的config中),在後面,咱們會看到它是如何加框第三方模塊的。 在繼續分析執行流程以前,咱們先介紹一些工具腳本。模塊化
cat << END >> $NGX_AUTO_CONFIG_H
#ifndef $have
#define $have 1
#endif
END
從代碼中,咱們能夠看到,這個工具的做用是,將$have變量的值,宏定義爲1,並輸出到auto_config文件中。一般咱們經過這個工具來控制是否打開某個特性。這個工具在使用前,須要先定義宏的名稱 ,即$have變量。函數
# NGX_DEBUG是在auto/options文件中處理的,若是有--with-debug選項,則其值是YES
if [ $NGX_DEBUG = YES ]; then
# 當有debug選項時,會定義NGX_DEBUG宏
have=NGX_DEBUG . auto/have
fi
這段代碼中,能夠看出,configure是如何定義一個特性的:經過宏定義,輸出到config頭文件中,而後在程序中能夠判斷這個宏是否有定義,來實現不一樣的特性。
configure文件中繼續向下:
# 編譯器選項
. auto/cc/conf
# 頭文件支持宏定義
if [ "$NGX_PLATFORM" != win32 ]; then
. auto/headers
fi
# 操做系統相關的配置的檢測
. auto/os/conf
# unix體系下的通用配置檢測
if [ "$NGX_PLATFORM" != win32 ]; then
. auto/unix
fi
configure會依次調用其它幾個文件,來進行環境的檢測,包括編譯器、操做系統相關。
nginx的configure會自動檢測不一樣平臺的特性,神奇之處就是auto/feature的實現,在繼續向下分析以前,咱們先來看看這個工具的實現原理。此工具的核心思想是,輸出一小段表明性c程序,而後設置好編譯選項,再進行編譯鏈接運行,再對結果進行分析。例如,若是想檢測某個庫是否存在,就在小段c程序裏面調用庫裏面的某個函數,再進行編譯連接,若是出錯,則表示庫的環境不正常,若是編譯成功,且運行正常,則庫的環境檢測正常。咱們在寫nginx第三方模塊時,也常使用此工具來進行環境的檢測,因此,此工具的做用貫穿整個configure過程。
先看一小段使用例子:
ngx_feature="poll()"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <poll.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int n; struct pollfd pl;
pl.fd = 0;
pl.events = 0;
pl.revents = 0;
n = poll(&pl, 1, 0);
if (n == -1) return 1"
. auto/feature
if [ $ngx_found = no ]; then
# 若是沒有找到poll,就設置變量的值
EVENT_POLL=NONE
fi
這段代碼在auto/unix裏面實現,用來檢測當前操做系統是否支持poll函數調用。在調用auto/feature以前,須要先設置幾個輸入參數變量的值,而後結果會存在$ngx_found變量裏面, 並輸出宏定義以表示支持此特性:
$ngx_feature 特性名稱
$ngx_feature_name 特性的宏定義名稱,若是特性測試成功,則會定義該宏定義
$ngx_feature_path 編譯時要查找頭文件目錄
$ngx_feature_test 要執行的測試代碼
$ngx_feature_incs 在代碼中要include的頭文件
$ngx_feature_libs 編譯時須要link的庫文件選項
$ngx_feature_run 編譯成功後,對二進制文件須要作的動做,能夠是yes value bug 其它
#ngx_found 若是找到,並測試成功,其值爲yes,不然其值爲no
看看ngx_feature的關鍵代碼:
# 初始化輸出結果爲no
ngx_found=no
#將特性名稱小寫轉換成大寫
if test -n "$ngx_feature_name"; then
# 小寫轉大寫
ngx_have_feature=`echo $ngx_feature_name \
| tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
fi
# 將全部include目錄轉換成編譯選項
if test -n "$ngx_feature_path"; then
for ngx_temp in $ngx_feature_path; do
ngx_feature_inc_path="$ngx_feature_inc_path -I $ngx_temp"
done
fi
# 生成臨時的小段c程序代碼。
# $ngx_feature_incs變量是程序須要include的頭文件
# $ngx_feature_test是測試代碼
cat << END > $NGX_AUTOTEST.c
#include <sys/types.h>
$NGX_INCLUDE_UNISTD_H
$ngx_feature_incs
int main() {
$ngx_feature_test;
return 0;
}
END
# 編譯命令
# 編譯以後的目標文件是 $NGX_AUTOTEST,後面會判斷這個文件是否存在來判斷是否編譯成功
ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"
# 執行編譯過程
# 編譯成功後,會生成$NGX_AUTOTEST命名的文件
eval "/bin/sh -c \"$ngx_test\" >> $NGX_AUTOCONF_ERR 2>&1"
# 若是文件存在,則編譯成功
if [ -x $NGX_AUTOTEST ]; then
case "$ngx_feature_run" in
# 須要運行來判斷是否支持特性
# 測試程序可否正常執行(即程序退出後的狀態碼是不是0),若是正常退出,則特性測試成功,設置ngx_found爲yes,並添加名爲ngx_feature_name的宏定義,宏的值爲1
yes)
# 若是程序正常退出,退出碼爲0,則程序執行成功,咱們能夠在測試代碼裏面手動返回非0來表示程序出錯
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
# 添加宏定義,宏的值爲1
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
else
echo " found but is not working"
fi
;;
# 須要運行程序來判斷是否支持特性,若是支持,將程序標準輸出的結果做爲宏的值
value)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
# 與yes不同的是,value會將程序從標準輸出裏面打印出來的值,設置爲ngx_feature_name宏變量的值
# 在此種狀況下,程序須要設置ngx_feature_name變量名
cat << END >> $NGX_AUTO_CONFIG_H
#ifndef $ngx_feature_name
#define $ngx_feature_name `$NGX_AUTOTEST`
#endif
END
else
echo " found but is not working"
fi
;;
# 與yes正好相反
bug)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " not found"
else
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
fi
;;
# 不須要運行程序,最後定義宏變量
*)
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
;;
esac
else
# 編譯失敗
echo " not found"
# 編譯失敗,會保存信息到日誌文件中
echo "----------" >> $NGX_AUTOCONF_ERR
# 保留編譯文件的內容
cat $NGX_AUTOTEST.c >> $NGX_AUTOCONF_ERR
echo "----------" >> $NGX_AUTOCONF_ERR
# 保留編譯文件的選項
echo $ngx_test >> $NGX_AUTOCONF_ERR
echo "----------" >> $NGX_AUTOCONF_ERR
fi
# 最後刪除生成的臨時文件
rm $NGX_AUTOTEST*
在瞭解了工具auto/feature後,繼續咱們的主流程,auto/cc/conf的代碼就很好理解了,這一步主要是檢測編譯器,並設置編譯器相關的選項。它先調用auto/cc/name來獲得編譯器的名稱,而後根據編譯器選擇執行不一樣的編譯器相關的文件如gcc執行auto/cc/gcc來設置編譯器相關的一些選項。
這個工具用來檢測是頭文件是否支持。須要檢測的頭文件放在$ngx_include裏面,若是支持,則$ngx_found變量的值爲yes,而且會產生NGX_HAVE_{ngx_include}的宏定義。
生成頭文件的宏定義。生成的定義放在objs/ngx_auto_headers.h裏面:
#ifndef NGX_HAVE_UNISTD_H #define NGX_HAVE_UNISTD_H 1 #endif #ifndef NGX_HAVE_INTTYPES_H #define NGX_HAVE_INTTYPES_H 1 #endif #ifndef NGX_HAVE_LIMITS_H #define NGX_HAVE_LIMITS_H 1 #endif #ifndef NGX_HAVE_SYS_FILIO_H #define NGX_HAVE_SYS_FILIO_H 1 #endif #ifndef NGX_HAVE_SYS_PARAM_H #define NGX_HAVE_SYS_PARAM_H 1 #endif
針對不一樣的操做系統平臺特性的檢測,並針對不一樣的操做系統,設置不一樣的CORE_INCS、CORE_DEPS、CORE_SRCS變量。nginx跨平臺的支持就是在這個地方體現出來的。
針對unix體系的通用配置或系統調用的檢測,如poll等事件處理系統調用的檢測等。
# 生成模塊列表
. auto/modules
# 配置庫的依賴
. auto/lib/conf
該腳本根據不一樣的條件,輸出不一樣的模塊列表,最後輸出的模塊列表的文件在objs/ngx_modules.c:
#include <ngx_config.h>
#include <ngx_core.h>
extern ngx_module_t ngx_core_module;
extern ngx_module_t ngx_errlog_module;
extern ngx_module_t ngx_conf_module;
extern ngx_module_t ngx_emp_server_module;
...
ngx_module_t *ngx_modules[] = {
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_emp_server_module,
...
NULL
};
這個文件會決定全部模塊的順序,這會直接影響到最後的功能,下一小節咱們將討論模塊間的順序。這個文件會加載咱們的第三方模塊,這也是咱們值得關注的地方:
if test -n "$NGX_ADDONS"; then
echo configuring additional modules
for ngx_addon_dir in $NGX_ADDONS
do
echo "adding module in $ngx_addon_dir"
if test -f $ngx_addon_dir/config; then
# 執行第三方模塊的配置
. $ngx_addon_dir/config
echo " + $ngx_addon_name was configured"
else
echo "$0: error: no $ngx_addon_dir/config was found"
exit 1
fi
done
fi
這段代碼比較簡單,確實現了nginx很強大的擴展性,加載第三方模塊。$ngx_addon_dir變量是在configure執行時,命令行參數–add-module加入的,它是一個目錄列表,每個目錄,表示一個第三方模塊。從代碼中,咱們能夠看到,它就是針對每個第三方模塊執行其目錄下的config文件。因而咱們能夠在config文件裏面執行咱們本身的檢測邏輯,好比檢測庫依賴,添加編譯選項等。
該文件會針對nginx編譯所須要的基礎庫的檢測,好比rewrite模塊須要的PCRE庫的檢測支持。
case ".$NGX_PREFIX" in
.)
NGX_PREFIX=${NGX_PREFIX:-/usr/local/nginx}
have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define
;;
.!)
NGX_PREFIX=
;;
*)
have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define
;;
esac
if [ ".$NGX_CONF_PREFIX" != "." ]; then
have=NGX_CONF_PREFIX value="\"$NGX_CONF_PREFIX/\"" . auto/define
fi
have=NGX_SBIN_PATH value="\"$NGX_SBIN_PATH\"" . auto/define
have=NGX_CONF_PATH value="\"$NGX_CONF_PATH\"" . auto/define
have=NGX_PID_PATH value="\"$NGX_PID_PATH\"" . auto/define
have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . auto/define
have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" . auto/define
have=NGX_HTTP_LOG_PATH value="\"$NGX_HTTP_LOG_PATH\"" . auto/define
have=NGX_HTTP_CLIENT_TEMP_PATH value="\"$NGX_HTTP_CLIENT_TEMP_PATH\""
. auto/define
have=NGX_HTTP_PROXY_TEMP_PATH value="\"$NGX_HTTP_PROXY_TEMP_PATH\""
. auto/define
have=NGX_HTTP_FASTCGI_TEMP_PATH value="\"$NGX_HTTP_FASTCGI_TEMP_PATH\""
. auto/define
have=NGX_HTTP_UWSGI_TEMP_PATH value="\"$NGX_HTTP_UWSGI_TEMP_PATH\""
. auto/define
have=NGX_HTTP_SCGI_TEMP_PATH value="\"$NGX_HTTP_SCGI_TEMP_PATH\""
. auto/define
# 生成objs/makefile文件
. auto/make
# 生成關於庫的編譯選項到makefile文件
. auto/lib/make
# 生成與安裝相關的makefile文件內容,並生成最外層的makefile文件
. auto/install
# STUB
. auto/stubs
have=NGX_USER value="\"$NGX_USER\"" . auto/define
have=NGX_GROUP value="\"$NGX_GROUP\"" . auto/define
# 編譯的最後階段,彙總信息
. auto/summary
上一節中,提到過,nginx模塊的順序很重要,會直接影響到程序的功能。並且,nginx和部分模塊,也有着本身特定的順序要求,好比ngx_http_write_filter_module模塊必定要在filter模塊的最後一步執行。想查看模塊的執行順序,能夠在objs/ngx_modules.c這個文件中找到,這個文件在configure以後生成,上一節中,咱們看過這個文件裏面的內容。
下面是一個ngx_modules.c文件的示例:
ngx_module_t *ngx_modules[] = {
// 全局core模塊
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_emp_server_module,
&ngx_emp_server_core_module,
// event模塊
&ngx_events_module,
&ngx_event_core_module,
&ngx_kqueue_module,
// 正則模塊
&ngx_regex_module,
// http模塊
&ngx_http_module,
&ngx_http_core_module,
&ngx_http_log_module,
&ngx_http_upstream_module,
// http handler模塊
&ngx_http_static_module,
&ngx_http_autoindex_module,
&ngx_http_index_module,
&ngx_http_auth_basic_module,
&ngx_http_access_module,
&ngx_http_limit_conn_module,
&ngx_http_limit_req_module,
&ngx_http_geo_module,
&ngx_http_map_module,
&ngx_http_split_clients_module,
&ngx_http_referer_module,
&ngx_http_rewrite_module,
&ngx_http_proxy_module,
&ngx_http_fastcgi_module,
&ngx_http_uwsgi_module,
&ngx_http_scgi_module,
&ngx_http_memcached_module,
&ngx_http_empty_gif_module,
&ngx_http_browser_module,
&ngx_http_upstream_ip_hash_module,
&ngx_http_upstream_keepalive_module,
//此處是第三方handler模塊
// http filter模塊
&ngx_http_write_filter_module,
&ngx_http_header_filter_module,
&ngx_http_chunked_filter_module,
&ngx_http_range_header_filter_module,
&ngx_http_gzip_filter_module,
&ngx_http_postpone_filter_module,
&ngx_http_ssi_filter_module,
&ngx_http_charset_filter_module,
&ngx_http_userid_filter_module,
&ngx_http_headers_filter_module,
// 第三方filter模塊
&ngx_http_copy_filter_module,
&ngx_http_range_body_filter_module,
&ngx_http_not_modified_filter_module,
NULL
};
http handler模塊與http filter模塊的順序很重要,這裏咱們主要關注一下這兩類模塊。
http handler模塊,在後面的章節裏面會講到多階段請求的處理鏈。對於content phase以前的handler,同一個階段的handler,模塊是順序執行的。好比上面的示例代碼中,ngx_http_auth_basic_module與ngx_http_access_module這兩個模塊都是在access phase階段,因爲ngx_http_auth_basic_module在前面,因此會先執行。因爲content phase只會有一個執行,因此不存在順序問題。另外,咱們加載的第三方handler模塊永遠是在最後執行。
http filter模塊,filter模塊會將全部的filter handler排成一個倒序鏈,因此在最前面的最後執行。上面的例子中,&ngx_http_write_filter_module最後執行,ngx_http_not_modified_filter_module最早執行。注意,咱們加載的第三方filter模塊是在copy_filter模塊以後,headers_filter模塊以前執行。