我們已經瞭解了 Nginx 的基本命令和架構原理,下麵該到最讓人頭疼也是最不容易理解的部分了,那就是 nginx.conf 這個配置文件,下麵從 Nginx 的指令開始,一步步來講解 Nginx 的配置。 Nginx 指令 先來看一個典型的 Nginx 配置文件示例。 從上面可以看到,這個配置文件中 ...
我們已經瞭解了 Nginx 的基本命令和架構原理,下麵該到最讓人頭疼也是最不容易理解的部分了,那就是 nginx.conf 這個配置文件,下麵從 Nginx 的指令開始,一步步來講解 Nginx 的配置。
Nginx 指令
先來看一個典型的 Nginx 配置文件示例。
main
http {
upstream { … }
split_clients {…}
map {…}
geo {…}
server {
if () {…}
location {
limit_except {…}
}
location {
location {
}
}
}
server {
}
}
從上面可以看到,這個配置文件中包含了多個指令塊,有些指令塊還是重覆的,那麼這在 Nginx 中是一個什麼樣的規則?接下來會慢慢介紹。
指令塊的嵌套
在 Nginx 配置文件中,指令塊是可以互相嵌套的,例如上面的示例,http 塊中可以包含多個 server 塊,server 塊中還會包含多個 location 塊,每一個塊中都有相應的指令。
而每一個指令都有 Context 上下文,也就是生效的環境,這在 Nginx 的官方文檔中說的很清楚,例如下麵的兩條指令,Context 中都表明瞭各自可以生效的環境,access_log 指令可以在多個上下文中生效:
Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default: access_log logs/access.log combined;
Context: http, server, location, if in location, limit_except
Syntax: log_format name [escape=default|json|none] string ...;
Default: log_format combined "...";
Context: http
指令的合併
在 Nginx 中,指令分為兩種,一種是值指令,一種是動作類指令:
- 值指令:存儲配置項的值,是用來配置某一個配置項的
- 可以合併
- 示例
- root
- access_log
- gzip
- 動作類指令:指定行為動作,往往表示接下來要做一件事情
- 不可以合併
- 示例
- rewrit
- proxy_pass
- 生效階段
- server_rewrite 階段
- rewrite 階段
- content 階段
這裡面的示例以及生效階段,後面都還會詳細講,這裡可以不用過多關註,既然指令分為兩種,那麼就有不同的繼承規則,下麵就來說一下。
值指令的繼承規則
例如下麵的配置文件,這裡面在 server 塊和 location 塊中都配置了 root 指令,Nginx 的繼承規則如下:
- 子配置不存在時,直接使用父配置塊的指令
- 子配置存在時,覆蓋父配置塊
server {
listen 8080;
root /home/geek/nginx/html;
access_log logs/geek.access.log main;
location /test {
root /home/geek/nginx/test;
access_log logs/access.test.log main;
}
location /dlib {
alias dlib/;
}
location / {
}
根據上面這兩條規則,第一個 location 使用自家的 root 指令,後面兩個 location 則使用 server 塊的 root 指令。這和編程語言中變數的作用域也是類似的,作用域更小的變數優先順序往往更高,Nginx 的指令也是一樣。
文檔中沒有的指令如何判斷生效範圍
對於很多第三方模塊,很可能文檔並不完善,這時候需要通過源碼來查看指令的生效範圍。需要明確下麵幾個問題:
- 指令在哪個塊下生效?
- 指令允許出現在哪些塊下?
這兩個問題是在源碼中定義的,例如:
static ngx_command_t ngx_http_core_commands[] = {
{ ngx_string("variables_hash_max_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_core_main_conf_t, variables_hash_max_size),
NULL },
......
從上面第三行可以看到,variables_hash_max_size
指令是在 main 塊下生效的。
還會有兩個回調方法:
- 在 server 塊生效,從 http 向 server 合併
char *(*merge_srv_conf)(ngx_conf_t*cf, void *prev, void *conf);
- 向 location 合併
char *(*merge_loc_conf)(ngx_conf_t*cf, void *prev, void *conf);
例如:
static ngx_http_module_t ngx_http_core_module_ctx = {
ngx_http_core_preconfiguration, /* preconfiguration */
ngx_http_core_postconfiguration, /* postconfiguration */
ngx_http_core_create_main_conf, /* create main configuration */
ngx_http_core_init_main_conf, /* init main configuration */
ngx_http_core_create_srv_conf, /* create server configuration */
ngx_http_core_merge_srv_conf, /* merge server configuration */
ngx_http_core_create_loc_conf, /* create location configuration */
ngx_http_core_merge_loc_conf /* merge location configuration */
};
ngx_http_module_t
這個結構體裡面,定義了很多回調方法,最後一個 ngx_http_core_merge_loc_conf
方法,就是制定合併規則的。這個方法定義了兩個參數,一個是父配置,一個是子配置:
static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_core_loc_conf_t *prev = parent;
ngx_http_core_loc_conf_t *conf = child;
ngx_uint_t i;
ngx_hash_key_t *type;
ngx_hash_init_t types_hash;
if (conf->root.data == NULL) {
......
這個方法表明瞭從父配置向子配置合併。
listen 指令的用法
listen 指令在 server 塊中生效,用來配置監聽哪些埠,由這些埠來處理請求。listen 指令的配置如下:
如示例所示,listen 指令可以監聽的類型有多種,可以配置監聽地址和埠,也可以是僅地址和僅埠,還可以僅監聽 IPv6 等等。
究竟是哪個 server 來處理請求
server_name 指令的用法
一個指令:server_name
server_name 指令是用來配置究竟是哪個 server 來處理我們的請求的。有時候,一個 server_name 中可能會有多個功能變數名稱,這時候是如何選擇的呢?
- server_name 指令後可以跟多個功能變數名稱,第一個是主功能變數名稱,多個功能變數名稱之間空格分隔
- 泛功能變數名稱:僅支持在最前或最後加 *,例如:
server_name *.taohui.tech
- 正則表達式匹配:
server_name www.taohui.tech ~^www\d+\.taohui\.tech$;
當 server_name 指令後有多個功能變數名稱時,會有一個 server_name_in_redirect 的配置,這個配置預設關閉,它使用來控制功能變數名稱重定向的,也就是這個配置開啟之後,請求過來會重定向到主功能變數名稱訪問。
Syntax server_name_in_redirect on | off;
Default server_name_in_redirect off;
Context http, server, location
-
還可以用正則表達式創建變數
-
# 使用 $1/$2 的方式引用變數 server { server_name ~^(www\.)?(.+)$; location / { root /sites/$2; } }
-
# 還可以通過加一個 ?<> 的方式來命名變數 server { server_name ~^(www\.)?(?<domain>.+)$; location / { root /sites/$domain; } }
-
-
特殊的配置規則
- .test.tech 可以匹配 test.tech *.test.tech
- _ 匹配所有功能變數名稱請求
- "" 匹配沒有傳遞 host 頭部的請求
server 匹配的順序
- 精確匹配(與順序無關)
- * 在前的泛功能變數名稱(與順序無關)
- * 在後的泛功能變數名稱(與順序無關)
- 按文件中的順序匹配正則表達式功能變數名稱
- default server
- 第 1 個
- listen 指定 default
這裡面 default server 有兩種指定方式,假如沒有配置 default server,那麼第一個 server 塊就會成為 default server,如果 listen 中配置了 default,那麼就會由配置的塊進行處理。
關註公眾號回覆 Nginx 領取知識圖譜