1. 基礎知識 1.1 基本配置 main # 全局配置 events { # nginx 工作模式配置 } http { # http 設置 .... server { # 伺服器主機配置 .... location { # 路由配置 .... } location path { .... } l ...
1. 基礎知識
1.1 基本配置
main # 全局配置
events { # nginx 工作模式配置
}
http { # http 設置
....
server { # 伺服器主機配置
....
location { # 路由配置
....
}
location path {
....
}
location otherpath {
....
}
}
server {
....
location {
....
}
}
upstream name { # 負載均衡配置
....
}
}
如果想要生成 nginx 規範配置,可以參考nginxconfig.io
下麵是 nginx
一些配置中常用的內置全局變數,你可以在配置的任何位置使用它們。
變數名 | 功能 |
---|---|
$host |
請求信息中的 Host ,如果請求中沒有 Host 行,則等於設置的伺服器名 |
$request_method |
客戶端請求類型,如 GET 、POST |
$remote_addr |
客戶端的 IP 地址 |
$args |
請求中的參數 |
$content_length |
請求頭中的 Content-length 欄位 |
$http_user_agent |
客戶端 agent 信息 |
$http_cookie |
客戶端 cookie 信息 |
$remote_addr |
客戶端的 IP 地址 |
$remote_port |
客戶端的埠 |
$server_protocol |
請求使用的協議,如 HTTP/1.0 、HTTP/1.1\ |
$server_addr |
伺服器地址 |
$server_name |
伺服器名稱 |
$server_port |
伺服器的埠號 |
1.2 location 匹配規則
語法規則:location [=|~|~*|^~] /uri/ { … }
模式 | 含義 |
---|---|
location = /uri | = 表示精確匹配,只有完全匹配上才能生效 |
location ^~ /uri | ^~ 開頭對 URL 路徑進行首碼匹配,並且在正則之前。 |
location ~ pattern | 開頭表示區分大小寫的正則匹配 |
location ~* pattern | 開頭表示不區分大小寫的正則匹配 |
location /uri | 不帶任何修飾符,也表示首碼匹配,但是在正則匹配之後 |
location / | 通用匹配,任何未匹配到其它 location 的請求都會匹配到,相當於 switch 中的 default |
首碼匹配時,Nginx 不對 url 做編碼,因此請求為 /static/20%/aa
,可以被規則 ^~ /static/ /aa
匹配到(註意是空格)
多個 location 配置的情況下匹配順序為:
- 首先精確匹配
=
- 其次首碼匹配
^~
- 其次是按文件中順序的正則匹配
- 然後匹配不帶任何修飾的首碼匹配。
- 最後是交給
/
通用匹配 - 當有匹配成功時候,停止匹配,按當前匹配規則處理請求
意:首碼匹配,如果有包含關係時,按最大匹配原則進行匹配。比如在首碼匹配:location /dir01
與 location /dir01/dir02
,如有請求 http://localhost/dir01/dir02/file
將最終匹配到 location /dir01/dir02
例子,有如下匹配規則:
location = / {
echo "規則 A";
}
location = /login {
echo "規則 B";
}
location ^~ /static/ {
echo "規則 C";
}
location ^~ /static/files {
echo "規則 X";
}
location ~ \.(gif|jpg|png|js|css)$ {
echo "規則 D";
}
location ~* \.png$ {
echo "規則 E";
}
location /img {
echo "規則 Y";
}
location / {
echo "規則 F";
}
那麼產生的效果如下:
- 訪問根目錄
/
,比如http://localhost/
將匹配規則 A
- 訪問
http://localhost/login
將匹配規則 B
,http://localhost/register
則匹配規則 F
- 訪問
http://localhost/static/a.html
將匹配規則 C
- 訪問
http://localhost/static/files/a.exe
將匹配規則 X
,雖然規則 C
也能匹配到,但因為最大匹配原則,最終選中了規則 X
。你可以測試下,去掉規則 X ,則當前 URL 會匹配上規則 C
。 - 訪問
http://localhost/a.gif
,http://localhost/b.jpg
將匹配規則 D
和規則 E
,但是規則 D
順序優先,規則 E
不起作用,而http://localhost/static/c.png
則優先匹配到規則 C
- 訪問
http://localhost/a.PNG
則匹配規則 E
,而不會匹配規則 D
,因為規則 E
不區分大小寫。 - 訪問
http://localhost/img/a.gif
會匹配上規則 D
, 雖然規則 Y
也可以匹配上,但是因為正則匹配優先,而忽略了規則 Y
。 - 訪問
http://localhost/img/a.tiff
會匹配上規則 Y
。
訪問 http://localhost/category/id/1111
則最終匹配到規則 F ,因為以上規則都不匹配,這個時候應該是 Nginx 轉發請求給後端應用伺服器,比如 FastCGI(php),tomcat(jsp),Nginx 作為反向代理伺服器存在。
理解 Nginx 中 Server 和 Location 的匹配邏輯
1.3 nginx 日誌
Nginx 日誌主要有兩種:access_log(訪問日誌) 和 error_log(錯誤日誌)。
1.3.1 access_log 訪問日誌
access_log 主要記錄客戶端訪問 Nginx 的每一個請求,格式可以自定義。通過 access_log 你可以得到用戶地域來源、跳轉來源、使用終端、某個 URL 訪問量等相關信息。
nginx log 文件預設地址 /var/log/nginx/
;
log_format 指令用於定義日誌的格式,語法: log_format name string;
其中 name 表示格式名稱,string 表示定義的格式字元串。log_format 有一個預設的無需設置的組合日誌格式。
預設的無需設置的組合日誌格式
log_format combined '$remote_addr - $remote_user [$time_local] '
' "$request" $status $body_bytes_sent '
' "$http_referer" "$http_user_agent" ';
access_log 指令用來指定訪問日誌文件的存放路徑(包含日誌文件名)、格式和緩存大小,語法:access_log path [format_name [buffer=size | off]];
其中 path 表示訪問日誌存放路徑,format_name 表示訪問日誌格式名稱,buffer 表示緩存大小,off 表示關閉訪問日誌。
log_format 使用示例:在 access.log 中記錄客戶端 IP 地址、請求狀態和請求時間
log_format myformat '$remote_addr $status $time_local';
access_log logs/access.log myformat;
需要註意的是:log_format 配置必須放在 http 內,否則會出現警告。Nginx 進程設置的用戶和組必須對日誌路徑有創建文件的許可權,否則,會報錯。
定義日誌使用的欄位及其作用:
欄位 | 作用 |
---|---|
$remote_addr 與 $http_x_forwarded_for | 記錄客戶端 IP 地址 |
$remote_user | 記錄客戶端用戶名稱 |
$request | 記錄請求的 URI 和 HTTP 協議 |
$status | 記錄請求狀態 |
$body_bytes_sent | 發送給客戶端的位元組數,不包括響應頭的大小 |
$bytes_sent | 發送給客戶端的總位元組數 |
$connection | 連接的序列號 |
$connection_requests | 當前通過一個連接獲得的請求數量 |
$msec | 日誌寫入時間。單位為秒,精度是毫秒 |
$pipe | 如果請求是通過 HTTP 流水線 (pipelined) 發送,pipe 值為“p”,否則為“.” |
$http_referer | 記錄從哪個頁面鏈接訪問過來的 |
$http_user_agent | 記錄客戶端瀏覽器相關信息 |
$request_length | 請求的長度(包括請求行,請求頭和請求正文) |
$request_time | 請求處理時間,單位為秒,精度毫秒 |
$time_iso8601 | ISO8601 標準格式下的本地時間 |
$time_local | 記錄訪問時間與時區 |
1.3.2 error_log 錯誤日誌
error_log 主要記錄客戶端訪問 Nginx 出錯時的日誌,格式不支持自定義。通過查看錯誤日誌,你可以得到系統某個服務或 server 的性能瓶頸等。因此,將日誌利用好,你可以得到很多有價值的信息。
error_log 指令用來指定錯誤日誌,語法: error_log path [level]
; 其中 path 表示錯誤日誌存放路徑,level 表示錯誤日誌等級,日誌等級包括 debug、info、notice、warn、error、crit、alert、emerg,從左至右,日誌詳細程度逐級遞減,即 debug 最詳細,emerg 最少,預設為 error。
註意:error_log off
並不能關閉錯誤日誌記錄,此時日誌信息會被寫入到文件名為 off 的文件當中。如果要關閉錯誤日誌記錄,可以使用如下配置:
Linux 系統把存儲位置設置為空設備
error_log /dev/null;
http {
# ...
}
Windows 系統把存儲位置設置為空設備
error_log nul;
http {
# ...
}
另外 Linux 系統可以使用 tail 命令方便的查閱正在改變的文件, tail -f filename 會把 filename 里最尾部的內容顯示在屏幕上, 並且不斷刷新, 使你看到最新的文件內容。Windows 系統沒有這個命令,你可以在網上找到動態查看文件的工具。
1.4 nginx 負載均衡
Upstream 指定後端伺服器地址列表,在 server 中攔截響應請求,並將請求轉發到 Upstream 中配置的伺服器列表。
upstream balanceServer {
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
server {
server_name fe.server.com;
listen 80;
location /api {
### 轉發到指定伺服器或url
proxy_pass http://balanceServer;
}
}
上面的配置只是指定了 nginx 需要轉發的服務端列表,並沒有指定分配策略。
預設情況下採用的是輪詢策略,將所有客戶端請求輪詢分配給服務端。這種策略是可以正常工作的,但是如果其中某一臺伺服器壓力太大,出現延遲,會影響所有分配在這台伺服器下的用戶。
1.5 nginx 常用命令
# 快速關閉 Nginx,可能不保存相關信息,並迅速終止 web 服務
nginx -s stop
# 平穩關閉 Nginx,保存相關信息,有安排的結束 web 服務
nginx -s quit
# 因改變了 Nginx 相關配置,需要重新載入配置而重載
nginx -s reload
# 重新打開日誌文件
nginx -s reopen
# 為 Nginx 指定一個配置文件,來代替預設的
nginx -c filename
# 不運行,而僅僅測試配置文件。nginx 將檢查配置文件的語法的正確性,並嘗試打開配置文件中所引用到的文件
nginx -t
# 顯示 nginx 的版本
nginx -v
# 顯示 nginx 的版本,編譯器版本和配置參數
nginx -V
# 格式換顯示 nginx 配置參數
2>&1 nginx -V | xargs -n1
2>&1 nginx -V | xargs -n1 | grep lua
2. 反向代理
location / {
### 反向代理的地址
proxy_pass http://localhost:8080/web/;
#以下三個proxy_set_header配置項是重點
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
proxy_set_header:讓後端伺服器能獲取到前端用戶真實IP,而不只是代理伺服器的IP。配置示例如下(還需將後端Apache日誌格式中的%h替換為%{X-Real-IP}i):
client_body_buffer_size:客戶端請求主體緩衝區大小
proxy_connect_timeout:代理伺服器和後端真實伺服器握手連接超時時間
proxy_send_timeout:後端伺服器回傳數據給Nginx的時間,需要在設置的時間範圍內發送完所有數據,否則Nginx將斷開連接
proxy_read_timeout:代理伺服器和後端伺服器連接成功後,等待後端伺服器響應時間
3. 負載均衡
3.1 常用參數
server:負載均衡後端伺服器的IP或功能變數名稱,不寫埠的話預設是80。高併發場景用功能變數名稱,再通過DNS進行負載均衡
weight:後端伺服器權重,預設為1,權重越大接收的請求越多。例:weight=5
max_fails:檢查節點的健康狀態並允許請求失敗的次數,達到該次數就將節點下線。預設為1,0表示禁止失敗嘗試。例:max_fails=2
fail_timeout:max_fails失敗次數達到限制後暫停該節點服務的時間,預設是10秒。例:fail_timeout=10s
backup:熱備配置,當服務池中所有伺服器均出現問題後會自動上線backup伺服器
d****own:標誌伺服器不可用,不參與負載均衡。這個參數通常配合IP_HASH使用
max_conns:限制最大連接數,通常對後端伺服器硬體不一致的情況進行配置
upstream linuxe_backend {
server 192.168.1.110 down; #該節點不可用
server 192.168.1.120 backup; #其他節點掛了後該節點自動上線
server 192.168.1.130 max_failes=1 fail_timeout=10s weight-5;
server backend1.linuxe.cn 8080 weight=3
}
3.2 預設的調度演算法
- 輪詢(預設);
- 加權輪詢;
- IP HASH;
3.3 實例
加權輪詢:
http {
upstream myserver{
server 192.168.1.100 weight=3; #指定後端伺服器地址,權重為3
server 192.168.1.110;
}
server {
listen 80;
server name www.myserver.com;
location / {
proxy_pass http://myserver;
}
}
IP HASH:
upstream myserver {
ip_hash; #採用IP HASH演算法
server 192.168.1.100;
server 192.168.1.110;
server 192.168.1.120;
}
URL HASH:
upstream myserver {
hash $request_uri;
server 192.168.1.100;
server 192.168.1.110;
server 192.168.1.120;
}
連接數輪詢:
http{
upstream sampleapp {
least_conn;
server <<dns entry or IP Address(optional with port)>>;
server <<another dns entry or IP Address(optional with port)>>;
}
....
server{
listen 80;
...
location / {
proxy_pass http://sampleapp;
}
}
4. Nginx location 和 proxy_pass路徑配置詳解
見文檔 Nginx location 和 proxy_pass路徑配置詳解
proxy_pass
,如果和location
都加了/
,lcoation
里的首碼會被去掉,參考文檔 proxy_pass詳解;
- 當在後面的
upstram_name
後面出現了/
,相當於是絕對根路徑,則nginx
不會把location
中匹配的路徑部分代理走; - 如果沒有
/
,則會把匹配的路徑部分也給代理走;
參考文章
[5] OpenResty 最佳實踐
[6] Nginx 核心知識 100 講
[7] 極客時間:nginx 核心知識 100 講配置文件與代碼分享
[8] OpenResty 從入門到實戰
[9] Nginx 基礎知識從小白到入門
[10] 【Nginx配置】使用upstream和proxy_pass實現反向代理與負載均衡
[11] Nginx location 和 proxy_pass路徑配置詳解