文章目錄
3.2 nginx架構
架構基礎
3.2.1 nginx進程結構
任何Unix應用程序的基本基礎都是線程或進程。
NGINX Worker流程內部
每個NGINX工作進程都使用NGINX配置初始化,並且由主進程提供一組偵聽套接字。
NGINX工作進程始於等待偵聽套接字上的事件(accept_mutex和內核套接字分片)。事件由新的傳入連接啓動。這些連接被分配給狀態機 -HTTP狀態機是最常用的,但是NGINX還爲流(原始TCP)流量和許多郵件協議(SMTP,IMAP和POP3)實現狀態機。
狀態機本質上是一組指令,用於告訴NGINX如何處理請求。大多數執行與NGINX相同功能的Web服務器都使用類似的狀態機-區別在於實現。
1.單進程結構
用於開發,調試環境
2.多進程結構
3.參考鏈接
https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/
3.2.2 epoll模型
Linux中IO複用工具:在Linux中先後出現了select、poll、epoll等,FreeBSD的kqueue也是非常優秀的IO複用工具,kqueue的原理和epoll很類似
參考知乎文章:https://www.zhihu.com/question/20122137/answer/14049112
流:一個流可以是文件,socket,pipe等等可以進行I/O操作的內核對象。
阻塞:比如某個時候你在等快遞,但是你不知道快遞什麼時候過來,而且你沒有別的事可以幹(或者說接下來的事要等快遞來了才能做);那麼你可以去睡覺了,因爲你知道快遞把貨送來時一定會給你打個電話(假定一定能叫醒你)。
非阻塞忙輪詢:接着上面等快遞的例子,如果用忙輪詢的方法,那麼你需要知道快遞員的手機號,然後每分鐘給他掛個電話:“你到了沒?”
爲了避免CPU空轉,可以引進了一個代理(一開始有一位叫做select的代理,後來又有一位叫做poll的代理,不過兩者的本質是一樣的)。
這個代理比較厲害,可以同時觀察許多流的I/O事件,在空閒的時候,會把當前線程阻塞掉,當有一個或多個流有I/O事件時,就從阻塞態中醒來,於是我們的程序就會輪詢一遍所有的流(於是我們可以把“忙”字去掉了)。
於是,如果沒有I/O事件產生,我們的程序就會阻塞在select處。
epoll可以理解爲event poll,不同於忙輪詢和無差別輪詢,epoll只會把哪個流發生了怎樣的I/O事件通知我們。此時我們對這些流的操作都是有意義的。(複雜度降低到了O(k),k爲產生I/O事件的流的個數,也有認爲O(1)的)
注:單個select最多隻能同時處理1024個socket。
select的做法:
步驟1的解法:select創建3個文件描述符集,並將這些文件描述符拷貝到內核中,這裏限制了文件句柄的最大的數量爲1024(注意是全部傳入—第一次拷貝);
步驟2的解法:內核針對讀緩衝區和寫緩衝區來判斷是否可讀可寫,這個動作和select無關;
步驟3的解法:內核在檢測到文件句柄可讀/可寫時就產生中斷通知監控者select,select被內核觸發之後,就返回可讀可寫的文件句柄的總數;
步驟4的解法:select會將之前傳遞給內核的文件句柄再次從內核傳到用戶態(第2次拷貝),select返回給用戶態的只是可讀可寫的文件句柄總數,再使用FD_ISSET宏函數來檢測哪些文件I/O可讀可寫(遍歷);
步驟5的解法:select對於事件的監控是建立在內核的修改之上的,也就是說經過一次監控之後,內核會修改位,因此再次監控時需要再次從用戶態向內核態進行拷貝(第N次拷貝)
epoll的做法:
步驟1的解法:首先執行epoll_create在內核專屬於epoll的高速cache區,並在該緩衝區建立紅黑樹和就緒鏈表,用戶態傳入的文件句柄將被放到紅黑樹中(第一次拷貝)。
步驟2的解法:內核針對讀緩衝區和寫緩衝區來判斷是否可讀可寫,這個動作與epoll無關;
步驟3的解法:epoll_ctl執行add動作時除了將文件句柄放到紅黑樹上之外,還向內核註冊了該文件句柄的回調函數,內核在檢測到某句柄可讀可寫時則調用該回調函數,回調函數將文件句柄放到就緒鏈表。
步驟4的解法:epoll_wait只監控就緒鏈表就可以,如果就緒鏈表有文件句柄,則表示該文件句柄可讀可寫,並返回到用戶態(少量的拷貝);
步驟5的解法:由於內核不修改文件句柄的位,因此只需要在第一次傳入就可以重複監控,直到使用epoll_ctl刪除,否則不需要重新傳入,因此無多次拷貝。
簡單說:epoll是繼承了select/poll的I/O複用的思想,並在二者的基礎上從監控IO流、查找I/O事件等角度來提高效率,具體地說就是內核句柄列表、紅黑樹、就緒list鏈表來實現的。
epoll高效的原因:
這是由於我們在調用epoll_create時,內核除了幫我們在epoll文件系統裏建了個file結點,在內核cache裏建了個紅黑樹用於存儲以後epoll_ctl傳來的socket外,還會再建立一個list鏈表,用於存儲準備就緒的事件.
當epoll_wait調用時,僅僅觀察這個list鏈表裏有沒有數據即可。有數據就返回,沒有數據就sleep,等到timeout時間到後即使鏈表沒數據也返回。所以,epoll_wait非常高效。
五種網絡IO模型和select/epoll對比:https://zhuanlan.zhihu.com/p/38277885
3.3 nginx模塊
3.3.1 動態模塊
nginx在編譯時可以將模塊編程成動態模塊,需要使用模塊時被可執行文件加載
./configure --XXX=dynamic
3.3.2 模塊本質
指令
內置變量
3.3.3 模塊指令
值指令:可以被局部的值指令覆蓋
動作指令:一旦滿足某條件直接執行
3.3.4 請求處理的11個階段
1.nginx模塊簡介
- 核心功能(Core Functionality)
參考網址:http://nginx.org/en/docs/ngx_core_module.html
功能:主要負責nginx的main區塊和event區塊,定義了nginx的全局參數
- http標準功能模塊集合
參考網址:http://nginx.org/en/docs/
模塊列表
2.請求處理流程示意圖
3.請求處理的11個階段
1.POST_READ
讀取請求頭後
realip
REALIP_MODULE模塊:https://my.oschina.net/xxj123go/blog/907041/print
1.1 模塊功能
在複雜集羣環境中remote_addr 爲反向代理的地址,而不是真實客戶端ip,realip用於獲取真正客戶端地址
1.2 模塊指令
set_real_ip_from 定義可信任的地址
real_ip_header 定義使用那個請求頭部
real_ip_recursive 如果最後一個地址是本機地址則去除,去去除後的非本機地址
1.3 模塊變量
$realip_remote_addr 替換之前的remote_addr
$realip_remote_port 替換之前的remote_port
1.4 模塊實戰
1.編輯hosts
192.168.217.155 www.pl.com realip.pl.com
2.安裝nginx(編譯realip到nginx)
./configire --prefix=/usr/local/nginx --with-http_realip_module
make
3.配置
nginx.conf
include conf.d/*.conf;
vi /usr/local/nginx/conf/conf.d/realip.conf
server {
listen 80;
server_name realip.pl.com;
error_log logs/realip.err_log;
set_real_ip_from 192.168.217.155;
#real_ip_header X_Real_IP;
#real_ip_recursive off;
real_ip_recursive off;
real_ip_header X-Forwarded-For;
location / {
return 200 "Client real ip: $realip_remote_addr $remote_addr\n";
}
}
當real_ip_recursive爲off時,nginx會把real_ip_header指定的HTTP頭中的最後一個IP當成真實IP
當real_ip_recursive爲on時,nginx會把real_ip_header指定的HTTP頭中的最後一個不是信任服務器的IP當成真實IP
4…測試
curl -H 'X-Forwarded-For:1.1.1.1,2.2.2.2' realip.pl.com
curl -H 'X-Forwarded-For:1.1.1.1,2.2.2.2,172.16.199.183' realip.pl.com
熱部署
nginx -s top
ps aux | grep nginx
kill -QUIT PID
ps aux | grep nginx
cd objs/nginx
cp objs/nginx /usr/local/nginx/sbin
2.SERVER_REWRITE
執行rewrite
rewrite模塊:https://www.cnblogs.com/beyang/p/7832460.html
2.1 模塊名稱
http_rewrite_module(默認)
2.2 模塊功能
return返回狀態碼
rewrite返回URL重定向
2.3 模塊指令
return
用戶對特定狀態碼返回不同url
返回狀態碼
- 444 關閉連接
- 301 永久重定向
- 302 臨時重定向,禁止被緩存
rewrite
對資源進行URL重寫
flags
--last
進行新的location匹配
--break
停止腳本指令的執行
--redirect
返回302重定向
--permanent
返回301重定向
if
條件判斷
條件規則
- 檢查變量爲空或者值是否爲0,直接使用
- 將變量與字符串做匹配,使用=或者!=
- 將變量與正則表達式做匹配
~或!~
~*或!~*
忽略大小寫 - 檢查文件是否存在,使用-f或者!-f
- 檢查目錄是否存在,使用-d或者!-d
- 檢查文件,目錄,軟鏈接是否存在,使用-e或者!-e
- 檢查是否爲可執行文件:使用-x或!-x
舉例
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
if ($request_method = POST) {
return 405;
}
if ($slow) {
limit_rate 10k;
}
if ($invalid_referer) {
return 403;
}
2.4 模塊實戰
1.目錄結構
/data/test/one 1.txt 內容test1
/data/test/two 2.txt 內容test2
/data/test/three 3.txt 內容test3
2.配置指令
server {
listen 80;
server_name rewrite.pl.com;
root /data/test/;
location /one {
rewrite /one(.*) /two$1 last;
return 200 'One\n';
}
location /two {
rewrite /two(.*) /three$1;
#rewrite /two(.*) /three$1 break;
return 200 'Two\n';
}
location /three {
return 200 'three\n';
}
}
3.問題
return與rewrite指令執行順序? rewrite
訪問/one/3.txt,/two/3.txt,three/3.txt分別返回的是什麼? Two Two three
如果不攜帶flag會怎樣?效果在以下測試體現。
4.測試
[root@www ~]# curl rewrite.pl.com/one/3.txt
Two
[root@www ~]# curl rewrite.pl.com/two/3.txt
Two
[root@www ~]# curl rewrite.pl.com/three/3.txt
three
測試break flag
rewrite /two(.*) /three$1 break;
[root@www ~]# curl rewrite.pl.com/two/3.txt
test3
3.FIND_CONFIG
關於一些對location認識的誤區:https://www.cnblogs.com/lidabo/p/4169396.html
根據uri替換location,僅在nginx框架中使用,沒有任何模塊在此階段生效
location 匹配用戶URI,並執行後面的配置段
location [匹配標識] 匹配網站URI { 匹配URI後執行的配置段 }
3.1 語法:
location URI 普通字符模糊匹配
location = URI 進行普通字符精確匹配
location ^~ URI ^~表示普通字符模糊匹配,如果該選項匹配,只匹配該選項,不匹配別的選項,一般用來匹配目錄
location ~ URI 波浪線表示執行一個正則匹配,區分大小寫
location ~* URI 表示執行一個正則匹配,不區分大小寫
3.2 匹配順序
1.遍歷匹配全部前綴字符串location
優先精確匹配=,匹配到不往下匹配
匹配到^~直接使用,不往下匹配
2.記住最長匹配的前綴字符串location
3.按nginx.conf的配置依次匹配正則表達式location
匹配,則使用其配置指令
不匹配則使用前面匹配到的最長的字符串location
3.3 示例
server {
listen 80;
server_name location.pl.com;
root html;
location / {
return 401;
}
location = / {
return 402;
}
location /documents/ {
return 403;
}
location ^~ /images/ {
return 404;
}
location ~* \.(gif|jpg|jpeg)$ {
return 500;
}
}
測試
[root@www ~]# curl -I http://location.pl.com
HTTP/1.1 402 Payment Required
Server: nginx/1.14.0
Date: Sat, 06 Jun 2020 01:58:46 GMT
Content-Type: text/html
Content-Length: 183
Connection: keep-alive
[root@www ~]# curl -I http://location.pl.com/
HTTP/1.1 402 Payment Required
Server: nginx/1.14.0
Date: Sat, 06 Jun 2020 01:59:14 GMT
Content-Type: text/html
Content-Length: 183
Connection: keep-alive
[root@www ~]# curl -I http://location.pl.com/index.html
HTTP/1.1 401 Unauthorized
Server: nginx/1.14.0
Date: Sat, 06 Jun 2020 01:59:56 GMT
Content-Type: text/html
Content-Length: 195
Connection: keep-alive
[root@www ~]# curl -I http://location.pl.com/documents/index.html
HTTP/1.1 403 Forbidden
Server: nginx/1.14.0
Date: Sat, 06 Jun 2020 02:00:19 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
[root@www ~]# curl -I http://location.pl.com/images/1.gif
HTTP/1.1 404 Not Found
Server: nginx/1.14.0
Date: Sat, 06 Jun 2020 02:00:39 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
[root@www ~]# curl -I http://location.pl.com/documents/q.jpg
HTTP/1.1 500 Internal Server Error
Server: nginx/1.14.0
Date: Sat, 06 Jun 2020 02:00:56 GMT
Content-Type: text/html
Content-Length: 193
Connection: close
結論
URI請求 | HTTP響應 |
---|---|
curl -I http://location.pl.com | 402 |
curl -I http://location.pl.com/ | 402 |
curl -I http://location.pl.com/index.html | 401 |
curl -I http://location.pl.com/documents/index.html | 403 |
curl -I http://location.pl.com/images/1.gif | 404 |
curl -I http://location.pl.com/documents/q.jpg | 500 |
4.REWRITE
根據替換結果繼續執行rewrite
rewrite
5.POST_REWRITE
執行rewrite後處理
6.PREACCESS
認證預處理,請求限制,連接限制
limit_conn
6.1 模塊名稱
http_limit_conn_module(默認編譯)
http_limit_conn_module:https://www.cnblogs.com/duanxz/p/3977756.html
對於一些服務器流量異常、負載過大,甚至是大流量的惡意攻擊訪問等,進行併發數的限制;該模塊可以根據定義的鍵來限制每個鍵值的連接數,只有那些正在被處理的請求(這些請求的頭信息已被完全讀入)所在的連接纔會被計數。
6.2 模塊指令
limit_conn_zone 定義共享內容大小,以及key關鍵字
limit_conn 限制併發連接數
limit_conn_log_level 限制發生時的日誌級別
limit_conn_status 向客戶端返回的錯誤碼
6.3 模塊實戰
配置
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
listen 80;
server_name limit.pl.com;
root html/;
location / {
limit_conn_status 500;
limit_conn_log_level warn;
limit_rate 50; #向用戶返回速率
limit_conn addr 1; #限制用戶併發連接數1
}
}
測試
會發現返回的內容是一行一行返回的。
克隆會話,同時發起連接。500
limit_req
限制每個客戶端的每秒處理請求數
6.4 模塊名稱
http_limit_req_module(默認編譯)
6.5 模塊算法
leaky bucket漏桶算法
漏桶算法:https://www.cnblogs.com/duanxz/p/4123068.html
水(請求)先進入到漏桶裏,漏桶以一定的速度出水(接口有響應速率),當水流入速度過大會直接溢出(訪問頻率超過接口響應速率),然後就拒絕請求,而當入小於出的情況下,漏桶不起任何作用。
6.6 模塊指令
limit_req_zone rate爲r/s,或者r/m
limit_req
limit_req_status 默認返回503
6.7 模塊實戰
驗證問題
limit_req delay 不delay有什麼區別?使用nodelay則表示不希望超過的請求被延遲。
limit_req與limit_conn配置同時生效,哪個有效?limit_req
limit_req
limit_conn
配置
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m;
server {
listen 80;
server_name limit.pl.com;
error_log logs/limit.err_log info;
root html/;
location / {
limit_conn_status 500;
limit_conn_log_level warn;
#limit_rate 50;
#limit_conn addr 1;
#limit_req zone=one burst=3 nodelay;
limit_req zone=one;
}
}
測試
單獨limit_req_zone
[root@www ~]# ab -n100 -c100 http://limit1.pl.com/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking limit1.pl.com (be patient).....done
Server Software: nginx/1.14.0
Server Hostname: limit1.pl.com
Server Port: 80
Document Path: /index.html
Document Length: 642 bytes
Concurrency Level: 100
Time taken for tests: 0.007 seconds
Complete requests: 100
Failed requests: 99
(Connect: 0, Receive: 0, Length: 99, Exceptions: 0)
Write errors: 0
Non-2xx responses: 99
Total transferred: 38990 bytes
HTML transferred: 21729 bytes
Requests per second: 14178.36 [#/sec] (mean)
Time per request: 7.053 [ms] (mean)
Time per request: 0.071 [ms] (mean, across all concurrent requests)
Transfer rate: 5398.58 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.3 1 2
Processing: 2 4 0.3 4 4
Waiting: 0 4 0.4 4 4
Total: 2 5 0.4 5 6
Percentage of the requests served within a certain time (ms)
50% 5
66% 6
75% 6
80% 6
90% 6
95% 6
98% 6
99% 6
100% 6 (longest request)
limit_req_zone
burst=3,使用nodelay則表示不希望超過的請求被延遲。
[root@www ~]# ab -n100 -c100 http://limit1.pl.com/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking limit1.pl.com (be patient).....done
Server Software: nginx/1.14.0
Server Hostname: limit1.pl.com
Server Port: 80
Document Path: /index.html
Document Length: 642 bytes
Concurrency Level: 100
Time taken for tests: 0.008 seconds
Complete requests: 100
Failed requests: 96
(Connect: 0, Receive: 0, Length: 96, Exceptions: 0)
Write errors: 0
Non-2xx responses: 96
Total transferred: 40460 bytes
HTML transferred: 23016 bytes
Requests per second: 13210.04 [#/sec] (mean)
Time per request: 7.570 [ms] (mean)
Time per request: 0.076 [ms] (mean, across all concurrent requests)
Transfer rate: 5219.51 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.3 1 2
Processing: 3 4 0.2 4 4
Waiting: 1 4 0.4 4 4
Total: 3 5 0.4 5 6
Percentage of the requests served within a certain time (ms)
50% 5
66% 6
75% 6
80% 6
90% 6
95% 6
98% 6
99% 6
100% 6 (longest request)
這時發現失敗爲96個。
同時配置
limit_req與limit_conn
[root@www ~]# ab -n100 -c100 http://limit1.pl.com/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking limit1.pl.com (be patient).....done
Server Software: nginx/1.14.0
Server Hostname: limit1.pl.com
Server Port: 80
Document Path: /index.html
Document Length: 642 bytes
Concurrency Level: 100
Time taken for tests: 0.007 seconds
Complete requests: 100
Failed requests: 99
(Connect: 0, Receive: 0, Length: 99, Exceptions: 0)
Write errors: 0
Non-2xx responses: 99
Total transferred: 38990 bytes
HTML transferred: 21729 bytes
Requests per second: 14275.52 [#/sec] (mean)
Time per request: 7.005 [ms] (mean)
Time per request: 0.070 [ms] (mean, across all concurrent requests)
Transfer rate: 5435.57 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.2 1 1
Processing: 2 4 0.2 4 4
Waiting: 1 4 0.3 4 4
Total: 2 5 0.3 5 5
Percentage of the requests served within a certain time (ms)
50% 5
66% 5
75% 5
80% 5
90% 5
95% 5
98% 5
99% 5
100% 5 (longest request)
失敗了99個,
關於limit_req和limit_conn的區別:
limit_req和limit_conn:https://www.cnblogs.com/duanxz/p/3967033.html
limit_req和limit_conn兩個模塊都是爲了來限流的,但是兩者不在一個層面
connection是連接,即常說的tcp連接,通過三次握手而建立的一個完整狀態機。建立一個連接,必須得要三次握手。
request是指請求,即http請求,(注意,tcp連接是有狀態的,而構建在tcp之上的http卻是無狀態的協議)。
通過打開一個網頁,然後通過wareshark可以看到,一個連接建立後(即三次握手後),在這個連接斷開之前(即四次揮手之前),會有很多的http request,這就是他們的區別:即一個連接的生命週期中,會存在一個或者多個請求,這是爲了加快效率,避免每次請求都要三次握手建立連接,現在的HTTP/1.1協議都支持這種特性,叫做keepalive。
7.ACCESS
認證處理
acess
7.1 模塊名稱
http_access_module(默認編譯)
http_access_module:https://www.cnblogs.com/wt645631686/p/8252915.html
Nginx基於access_module有侷限性
原理:基於客戶端的IP,但是對於Nginx來說,它不會管你哪個是真正的客戶端,如果我們的訪問不是客戶端與服務端直接連接,而是通過了一層代理,比如它的代理可以負載均衡、CDN的這種代理實現,也就是我們的訪問不是客戶端直接訪問的服務端,而是通過其他的中間件訪問服務端,這時候會出現一個問題,因爲Nginx的access_module它是基於remote_addr這個變量來識別客戶端的IP的,那麼如果一個ip通過中間件訪問服務端,那麼Nginx認爲訪問的ip就是中間件的IP,那麼我們在基於IP做限制的時候,那麼其實是沒有作用的。所以這樣的話,準確性是不高的,所以就是利用nginx的access_module有侷限性。
解決:
(1)HTTP_X_FORWARDED_FOR。
(2)結合geo模塊
(3)通過HTTP自定義變量傳遞
7.2 模塊功能
對IP做訪問控制
7.3 模塊指令
allow
deny
7.4 模塊實戰
[root@www ~]# vim /usr/local/nginx/conf/conf.d/access.conf
server {
listen 80;
server_name access.pl.com;
root /data/access/;
location / {
deny 192.168.217.155;
#allow 192.168.217.154;
allow 192.168.217.0/24;
allow 10.0.0.0/16;
allow 2001:0db8::/32;
deny all;
index index.html;
}
}
#從上到下的順序,類似iptables。匹配到了便跳出。如上的例子先禁止了192.168.217.155,接下來允許了3個網段,其中包含了一個ipv6,最後未匹配的IP全部禁止訪問.被deny的將返回403狀態碼。
在192.168.217.155測試
[root@www ~]# curl access.pl.com
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
在192.168.217.154測試
[root@localhost ~]# curl access.pl.com
<h1> access </h1>
auth_basic
7.5 模塊名稱
http_auth_basic_module(默認)
7.6 模塊功能
驗證用戶密碼
7.7 模塊指令
auth_basic 定義認證字符串
auth_basic_user_file 用戶密碼文件
通過htpasswd生成(包名httpd-tools)
htpasswd -c file -b user password
7.8 模塊實戰
配置
[root@www ~]# vim /usr/local/nginx/conf/conf.d/auth.conf
server {
listen 80;
server_name auth.pl.com;
root /data/auth/;
location / {
satisfy any;
auth_basic "closed site";
auth_basic_user_file htpasswd;
index index.html;
}
}
密碼生成
[root@www ~]# htpasswd -c /usr/local/nginx/conf/htpasswd alice
New password:
Re-type new password:
Adding password for user alice
測試
[root@www ~]# curl auth.pl.com
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
在瀏覽器上測試
輸入用戶名密碼
結果
auth_request
7.9 模塊名稱
http_auth_request_module(未編譯)
http_auth_request_module:https://blog.csdn.net/qq_34556414/article/details/105809958
7.10 模塊功能
向上遊服務器轉發請求,若上游服務返回2xx狀態碼,則繼續執行,若返回401或者403則響應給客戶端
7.11 模塊指令
auth_request uri|off;
auth_request_set $variable_name
7.12 模塊實戰
倆個虛擬主機,一個模擬代理,一個模擬上游
代理
[root@www ~]# vim /usr/local/nginx/conf/conf.d/auth_req.conf
server {
listen 80;
server_name auth_req.server.com;
root /data/auth_req;
location / {
auth_request /test_auth;
}
location = /test_auth{
proxy_pass http://auth.pl.com/auth_test;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
}
上游服務器
[root@www ~]# vim /usr/local/nginx/conf/conf.d/auth.conf
server {
listen 80;
server_name auth.pl.com;
root /data/auth/;
location / {
#isatisfy any;
#auth_basic "closed site";
#auth_basic_user_file htpasswd;
index index.html;
}
location /auth_test {
index index.html;
#return 200 'auth success';
return 403 'auth fail';
}
}
測試return 200 ‘auth success’;
更改return 403 ‘auth fail’;
satisfy指令
值爲all,代表access階段所有模塊都放行才放行請求,值爲any,代表access階段所有模塊只要任意一個放行就放行
satisfy any|all;
8.POST_ACCESS
認證後處理, 認證不通過, 丟包
9.PRECONTENT
嘗試try標籤
try_files
9.1 模塊名稱
http_try_files_module(默認編譯)
http_try_files_module:https://blog.csdn.net/qq_34556414/article/details/105823587
9.2 模塊功能
依次試圖訪問多個url對應的文件(由root或者alias指令指定),當文件存在時返回文件內容,如果所有文件都不存在,則最後一個URL結果或者code返回
在搭建wordpress站點的時候可以使用到try_files指令。該指令用於反向代理達到場景非常有用,可以先去嘗試在nginx上直接獲取磁盤上的內容,如果沒有這個文件再反向代理到上游服務。
9.3 模塊指令
9.4 模塊實戰
[root@www mirrors]# vim /usr/local/nginx/conf/conf.d/try_files.conf
server {
listen 80;
server_name try_files.pl.com;
root /data/try_files/;
location /one {
try_files /mirrors/admin.html
$uri $uri/index.html $uri.html
@lasturl;
}
location @lasturl {
return 200 "this is the lastest url\n";
}
location /two {
try_files $uri $uri/index.html $uri.html =404;
}
}
測試
[root@www mirrors]# curl try_files.pl.com/one
this is the lastest url
404
10.CONTENT
內容處理
index 返回index指定文件的內容
autoindex
10.1 模塊說明
返回root/alias指定目錄中文件列表,用於共享文件
10.2 模塊指令
autoindex on|off; autoindex開關
autoindex_exec_size on|off; 返回精確大小單位還是自動轉換大小單位
autoindex_format html | xml | json | jsonp; 返回默認頁面格式
autoindex_localtime on|off; 顯示時間
static
10.3 模塊功能
用於映射url到指令目錄中
10.4 模塊指令
root
完整url映射進文件路徑中
root html/one;
one--> /tmp
document_root /usr/local/nginx/html/one
realpath_root
alias
只將location後的URL映射到文件路徑
type
根據types指令中mime類型和文件後綴返回centent_type的類型
types {text/html html;image/gif gif;}
default_type
後綴爲知是默認返回的content_type,默認值是text/plain
log_not_found on|off
關閉文件未找到的日誌記錄,提升大量文件未找到時的日誌記錄性能
10.5 模塊變量
$request_filename 待訪問文件的完整路徑
$document_root 由URL和root/alias規則生成的目錄路徑
$realpath_root 將document_root中軟鏈接等替換成真實路徑
10.6 模塊實戰1
配置
[root@www ~]# vim /usr/local/nginx/conf/conf.d/static.conf
server_name static.pl.com;
server {
listen 80;
server_name static.pl.com;
location /root {
root /data/static/html;
}
location /alias {
alias /data/static/html;
}
location ~ /root/(\w+\.txt) {
root /data/static/html/one/$1;
}
location ~ /alias/(\w+\.txt) {
alias /data/static/html/one/$1;
}
}
測試
訪問不同url結果
/root ------- html/root
/root/33.txt ------- html/one/33.txt/root/33.txt
/alias ------- html/
/alias/3.txt ------- html/one/3.txt
這裏爲了更真實,在各路徑下都創建了文件。。。
訪問http://static.pl.com/roo
訪問http://static.pl.com/root/33.txt
訪問http://static.pl.com/alias
訪問http://static.pl.com/alias/3.txt
10.7 模塊實戰2
測試3個變量意義
配置
[root@www ~]# vim /usr/local/nginx/conf/conf.d/static.conf
server {
listen 80;
server_name static.pl.com;
location /root {
root /data/static/html;
}
location /alias {
alias /data/static/html;
}
location ~ /root/(\w+\.txt) {
root /data/static/html/one/$1;
}
location ~ /alias/(\w+\.txt) {
alias /data/static/html/one/$1;
}
location /test {
alias /data/static/html/new;
return 200 "$request_filename $document_root $realpath_root\n";
}
}
測試 curl static.pl.com/test/3.txt
[root@www ~]# curl static.pl.com/test/3.txt
/data/static/html/new/3.txt /data/static/html/new /data/static/html/new
$request_filename 待訪問文件的完整路徑
$document_root 由URL和root/alias規則生成的目錄路徑
$realpath_root 將document_root中軟鏈接等替換成真實路徑
11.LOG
日誌處理
error_log
access_log
11.1 模塊名稱
http_log_module
11.2 模塊功能
將http請求相關信息記錄到日誌
11.3 模塊指令
log_format 定義access日誌格式,默認格式combined
access_log
path 可以包含變量,不打開cache時每條日誌都需要打開關閉日誌文件
if=condition 通過變量值控制請求日誌是否記錄
buffer=size flush=time 日誌緩存
-
開啓日誌緩存,批量將內存中的日誌寫入磁盤
-
日誌寫入磁盤的條件
所有待寫入磁盤的日誌大小超出緩存大小
達到flush指定的過期時間
worker進程執行reopen命令,或者正在關閉
gzip=level 日誌壓縮
功能
- 批量壓縮內存中的日誌,再寫入磁盤
- buffer大小默認64k
- 壓縮級別默認爲1(壓縮率低->高,1-9)
open_log_file_cache
對日誌文件包含變量時的優化,由於如果日誌文件包含變量名會導致日誌文件頻繁打開關閉影響性能
max 緩存內的最大文件句柄數,超出的最少被使用的句柄會被關閉
inactive 文件訪問完後在這段時間內不會被關閉。默認10秒
min_uses 在inactive時間內使用次數超過min_uses纔會被繼續存在內容中。默認1
valid 超出valid時間後,將對緩存的日誌檢查是否存在。默認60秒
off 關閉緩存功能
11.4 error_log
錯誤日誌
error_log FILE [LEVEL]
eg: error_log logs/pl.com_err.log
11.5 日誌切割
nginx日誌模塊會將日誌記錄到指定日誌文件中,但時間一久日誌文件會越來越大,故需要做日誌切割
切割腳本
nginx_log_rotate.sh
#!/bin/bash
Dateformat=`date +%Y%m%d`
Basedir="/usr/local/nginx"
Nginxlogdir="$Basedir/logs"
Logname="access_pl.com"
[ -d $Nginxlogdir ] && cd $Nginxlogdir||exit 1
[ -f ${Logname}.log ]||exit 1
/bin/mv ${Logname}.log ${Dateformat}_${Logname}.log
$Basedir/sbin/nginx -s reload
將腳本寫入cron定時切割
logrotate