Nginx 的配置指令

我們已經瞭解了 Nginx 的基本命令和架構原理,下面該到最讓人頭疼也是最不容易理解的部分了,那就是 nginx.conf 這個配置文件,下面從 Nginx 的指令開始,一步步來講解 Nginx 的配置。

Nginx 指令

先來看一個典型的 Nginx 配置文件示例。

<code>main
http {
upstream { … }
split_clients {…}
map {…}
geo {…}
server {
if () {…}
location {
limit_except {…}
}
location {
location {
}
}
}
server {
}
}/<code>

從上面可以看到,這個配置文件中包含了多個指令塊,有些指令塊還是重複的,那麼這在 Nginx 中是一個什麼樣的規則?接下來會慢慢介紹。

指令塊的嵌套

在 Nginx 配置文件中,指令塊是可以互相嵌套的,例如上面的示例,http 塊中可以包含多個 server 塊,server 塊中還會包含多個 location 塊,每一個塊中都有相應的指令。

而每一個指令都有 Context 上下文,也就是生效的環境,這在 Nginx 的官方文檔中說的很清楚,例如下面的兩條指令,Context 中都表明了各自可以生效的環境,access_log 指令可以在多個上下文中生效:

<code>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/<code>

指令的合併

在 Nginx 中,指令分為兩種,一種是值指令,一種是動作類指令:

  • 值指令:存儲配置項的值,是用來配置某一個配置項的 可以合併 示例 root access_log gzip
  • 動作類指令:指定行為動作,往往表示接下來要做一件事情 不可以合併 示例 rewrit proxy_pass 生效階段 server_rewrite 階段 rewrite 階段 content 階段

這裡面的示例以及生效階段,後面都還會詳細講,這裡可以不用過多關注,既然指令分為兩種,那麼就有不同的繼承規則,下面就來說一下。

值指令的繼承規則

例如下面的配置文件,這裡面在 server 塊和 location 塊中都配置了 root 指令,Nginx 的繼承規則如下:

  • 子配置不存在時,直接使用父配置塊的指令
  • 子配置存在時,覆蓋父配置塊
<code>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 / {
}/<code>

根據上面這兩條規則,第一個 location 使用自家的 root 指令,後面兩個 location 則使用 server 塊的 root 指令。這和編程語言中變量的作用域也是類似的,作用域更小的變量優先級往往更高,Nginx 的指令也是一樣。

文檔中沒有的指令如何判斷生效範圍

對於很多第三方模塊,很可能文檔並不完善,這時候需要通過源碼來查看指令的生效範圍。需要明確下面幾個問題:

  1. 指令在哪個塊下生效?
  2. 指令允許出現在哪些塊下?

這兩個問題是在源碼中定義的,例如:

<code>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 },
....../<code>

從上面第三行可以看到,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);

例如:

<code>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 */
};/<code>

ngx_http_module_t 這個結構體裡面,定義了很多回調方法,最後一個 ngx_http_core_merge_loc_conf 方法,就是制定合併規則的。這個方法定義了兩個參數,一個是父配置,一個是子配置:

<code>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) {
....../<code>

這個方法表明了從父配置向子配置合併。

listen 指令的用法

listen 指令在 server 塊中生效,用來配置監聽哪些端口,由這些端口來處理請求。listen 指令的配置如下:

Nginx 的配置指令

如示例所示,listen 指令可以監聽的類型有多種,可以配置監聽地址和端口,也可以是僅地址和僅端口,還可以僅監聽 IPv6 等等。

究竟是哪個 server 來處理請求

server_name 指令的用法

一個指令:server_name

server_name 指令是用來配置究竟是哪個 server 來處理我們的請求的。有時候,一個 server_name 中可能會有多個域名,這時候是如何選擇的呢?

  1. server_name 指令後可以跟多個域名,第一個是主域名,多個域名之間空格分隔
  2. 泛域名:僅支持在最前或最後加 *,例如:server_name *.taohui.tech
  3. 正則表達式匹配:server_name www.taohui.tech ~^www\\d+\\.taohui\\.tech$;

當 server_name 指令後有多個域名時,會有一個 server_name_in_redirect 的配置,這個配置默認關閉,它使用來控制域名重定向的,也就是這個配置開啟之後,請求過來會重定向到主域名訪問。

<code>Syntax  server_name_in_redirect on | off;
Default server_name_in_redirect off;
Context http, server, location/<code>
  1. 還可以用正則表達式創建變量 # 使用 $1/$2 的方式引用變量 server { server_name ~^(www\\.)?(.+)$; location / { root /sites/$2; } } # 還可以通過加一個 ?<> 的方式來命名變量 server { server_name ~^(www\\.)?(?<domain>.+)$; location / { root /sites/$domain; } }/<domain>
  2. 特殊的配置規則 .test.tech 可以匹配 test.tech *.test.tech _ 匹配所有域名請求 "" 匹配沒有傳遞 host 頭部的請求

server 匹配的順序

  1. 精確匹配(與順序無關)
  2. * 在前的泛域名(與順序無關)
  3. * 在後的泛域名(與順序無關)
  4. 按文件中的順序匹配正則表達式域名
  5. default server 第 1 個 listen 指定 default

這裡面 default server 有兩種指定方式,假如沒有配置 default server,那麼第一個 server 塊就會成為 default server,如果 listen 中配置了 default,那麼就會由配置的塊進行處理。


分享到:


相關文章: