Nginx 的 Http 模塊介紹(下)
本小節(jié),我們將主要介紹 Nginx 中 Http 請求 11 個(gè)階段中的最后幾個(gè)重要的階段以及相關(guān)的模塊,并演示其用法。
1. try_files 階段
這個(gè)階段又稱為 precontent 階段,是 content 階段的前置處理階段,該階段主要介入的模塊是 ngx_http_try_files_module 模塊。該模塊依次訪問多個(gè) URI 對應(yīng)得文件(由 root 或者 alias 指令指定),當(dāng)文件存在時(shí)直接返回內(nèi)容,如果所有文件不存在,則按最后一個(gè) URL 結(jié)果或者 code 返回。
Syntax: try_files file ... uri;
try_files file ... =code;
Default: —
Context: server, location
2. content 階段
content 階段中最主要的 static 模塊,該模塊提供了root 和 alias 這兩個(gè)常用的指令。二者的用法如下:
Syntax: alias path
Default: —
Context: location
Syntax: root path
Default: root html
Context: http, server, location, if in location
可以看到,單從指令用法上就可以看到不少區(qū)別,首先是 alias 指令沒有默認(rèn)值,而且該指令只能在 location 中使用。而 root 可以存在與 http、server、location 等多個(gè)指令塊中,還可以出現(xiàn)在 if 指令中。另外,最最主要的不同是兩個(gè)指令會(huì)以不同的方式將請求映射到服務(wù)器文件上。root 指令會(huì)用[root 路徑 + location 路徑]的規(guī)則映射靜態(tài)資源請求,而 alias 會(huì)使用 alias 的路徑替換 location 路徑。
此外 alias 后面必須要用“/”結(jié)束,否則會(huì)找不到文件的,而 root 則可有可無。來看下面一個(gè)例子:
location ^~ /test {
root /root/html/;
}
location ^~ /test2/ {
alias /root/html/;
}
對于 http 請求: http://ip:端口/test/web1.html
訪問的是主機(jī) 上全路徑為 /root/html/test/web1.html
的靜態(tài)資源;而請求http://ip:端口/test2/web1.html
訪問的是全路徑為/root/html/web1.html
的靜態(tài)資源,/test2/已經(jīng)被替換掉了。
在 static 模塊中,還提供了 3 個(gè)變量供我們使用,分別是:
- request_filename: 訪問靜態(tài)資源的完整路徑
- document_root: 訪問靜態(tài)資源文件所在目錄
- realpath_root: 如果 document_root 是軟鏈接,則改變量會(huì)將其替換成真正的地址
同樣是上面的例子,稍做改動(dòng):
location /web {
default_type text/html;
alias /root/test/web;
return 200 '$request_filename:$document_root:$realpath_root\n';
}
訪問 http://ip:端口//web/web1.html
, 返回的結(jié)果為:
/root/test/web/web1.html:/root/test/web:/root/test/web
在 content 階段,在 static 模塊之前,還會(huì)執(zhí)行的模塊有 index 和 autoindex模塊。index 模塊提供了 index 指令,用于指定/訪問時(shí)返回 index 文件內(nèi)容。
autoindex 模塊會(huì)根據(jù)配置決定是否以列表的形式展示目錄下的內(nèi)容,這個(gè)功能在后續(xù)實(shí)戰(zhàn)中搭建內(nèi)部 pip 源中會(huì)用到。
Syntax: index file ...;
Default: index index.html;
Context: http, server, location
# 示例,訪問 uri=/ 時(shí),返回靜態(tài)資源 index.html 文件中的內(nèi)容
location / {
index index.html;
}
# 是否開啟目錄顯示,默認(rèn)Nginx是不會(huì)顯示目錄下的所有文件
Syntax: autoindex on | off;
Default: autoindex off;
Context: http, server, location
# 顯示出文件的實(shí)際大小
Syntax: autoindex_exact_size on | off;
Default: autoindex_exact_size on;
Context: http, server, location
# 顯示格式,默認(rèn)是html形式顯示
Syntax: autoindex_format html | xml | json | jsonp;
Default: autoindex_format html;
Context: http, server, location
# 顯示時(shí)間,設(shè)置為on后,按照服務(wù)器的時(shí)鐘為準(zhǔn)
Syntax: autoindex_localtime on | off;
Default: autoindex_localtime off;
Context: http, server, location
3. log 階段
log 階段是 http 請求 11 個(gè)階段中的最后一個(gè)階段,這個(gè)階段主要的任務(wù)就是記錄請求的訪問日志。這個(gè)階段主要涉及的是 ngx_http_log_module 這個(gè)模塊。該模塊提供了幾個(gè)常用指令,如 access_log 和 log_format 指令,分別定義了請求日志的記錄文件以及記錄的日志格式。
# 官方例子
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
access_log /spool/logs/nginx-access.log compression buffer=32k;
# 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
# log_format指令用法
Syntax: log_format name [escape=default|json|none] string ...;
Default: log_format combined "...";
Context: http
# 是否打開日志緩存
Syntax: open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
Default: open_log_file_cache off;
Context: http, server, location
4. 案例測試
4.1 try_files 模塊的示例
在測試機(jī)器的 /root/test/web 目錄下有 2 個(gè) html 文件,分別為 web.html 和 web2.html, 沒有 web3.html。我們編寫如下的 server 塊,監(jiān)聽 8013 端口。首先訪問 http://主機(jī)ip:8013/web 時(shí),根據(jù)配置情況,Nginx 首先查找是否存在 /root/test/web/web3.html 文件,沒有找到會(huì)繼續(xù)向下,找$uri,也就是/root/test/web 文件,不存在。繼續(xù)找 KaTeX parse error: Expected 'EOF', got ',' at position 15: uri/index.html,?即/root/test/web…uri/web1.html時(shí)文件存在,故返回/root/test/web/web1.html文件內(nèi)容。如果該文件還不存在,則還會(huì)繼續(xù)批評額哦@lasturi,最后返回’lasturi!'這樣的字符串。而在訪問 http://主機(jī)ip:8013/return_code 時(shí),由于無法匹配靜態(tài)資源,根據(jù)配置最后返回404錯(cuò)誤碼,出現(xiàn) Nginx 默認(rèn)的 404 錯(cuò)誤頁面。
server {
server_name try_files.com;
listen 8013;
root /root/test/;
default_type text/plain;
location /web {
# 找/root/test/index.html
# try_files /index.html
try_files /web/web3.html
$uri $uri/index.html $uri/web1.html
@lasturi; #最后匹配這個(gè)
}
location @lasturi {
eturn 200 'lasturi!\n';
}
location /return_code {
try_files $uri $uri/index.html $uri.html =404;
}
}
4.2 access_log 指令用法示例
我們只需要在 http 指令塊中配置 log_format 指令和 access_log 指令即可。測試的配置如下:
...
http {
...
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
# 和上面的日志格式無關(guān)
server {
listen 8000;
return 200 '8000, server\n';
}
...
}
...
log_format 指令是指定打印日志的格式,access_log 指令指定日志輸出的路徑以及指定使用前面定義的日志格式。在配置好日志相關(guān)的指令后,重啟 Nginx,并發(fā)送一個(gè) Http 請求,就可以在對應(yīng)的路徑上看到相關(guān)的日志信息了。
# 模擬發(fā)送http請求
[shen@shen Desktop]$ curl http://180.76.152.113:8000
8000, server
[shen@shen Desktop]$ curl -H "X-Forwarded-For: 1.1.1.1" http://180.76.152.113:8000
# 查看打印的日志,和前面配置的日志格式進(jìn)行對比
[root@server nginx]# tail -2 logs/access.log
103.46.244.226 - - [02/Feb/2020:20:52:05 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "-"
103.46.244.226 - - [02/Feb/2020:20:57:03 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "1.1.1.1"
5. 小結(jié)
本節(jié)內(nèi)容介紹了 Http 請求 11 個(gè)階段中的最后幾個(gè),分別是 try_files 階段、content 階段和 log 階段,同時(shí)還有對應(yīng)階段中生效的指令。這些在配置靜態(tài)資源訪問時(shí)非常有用,因?yàn)橹饕巧婕暗阶x取靜態(tài)資源的內(nèi)容。最后的 log 模塊也是非常重要的一步,良好的日志記錄有助于我們后續(xù)排查問題以及分析系統(tǒng)性能瓶頸。今天 Http 請求的 11 個(gè)處理階段正式講完,后面還需要多多深入每個(gè)階段的指令學(xué)習(xí)和實(shí)驗(yàn),徹底掌握 Nginx 的 Http 模塊。