按部就班Nginx將分紅三節來說
1.介紹、安裝、hello world、Location匹配(已完成)✅
2.反向代理、負載均衡、緩存服務、靜態資源訪問(已完成)✅
3.日誌管理、http限流、https配置,http_rewrite模塊,第三方模塊安裝,結語。(已完成)✅php
💡netcraft的數據統計顯示nginx是目前最受歡迎的web服務器:
html
若是你不懂理解下面的場景,那你就把你學習的意圖定爲「學習最受歡迎的服務器」也行,通常來講你都會有機會去使用nginx。固然也有可能分工過於明確致使你沒機會去碰部署相關的東西。linux
💡有時候文檔纔是最有用的教程,個人教程並不會講的很詳盡,那麼當你遇到問題的時候,參考文檔也是不錯的選擇。好比說我講了某個指令能夠用在A上下文,但沒說能不能用在B上下文的時候,你能夠參考一下官方文檔對於這個指令的上下文說明。
💡nginx中文文檔沒翻譯什麼,但在入門階段,你可能更想看到一點中文的東西。指令雖然老舊,但部分仍是有參考價值的
💡英文原始文檔,注意中文文檔通常會比較舊,有些指令可能會沒有,但入門初期還能用。
💡文檔裏面會分不少模塊,每一塊點進去能夠看到相似以下的說明:
💡你點進去文檔的話會看到不少模塊,模塊的話,你能夠認爲模塊用於劃分功能,好比HTTP Core模塊提供了核心的Http功能,負載均衡依賴於模塊HTTP Upstream,訪問控制依賴於HttpAccess模塊,Https依賴於HttpSSL模塊。nginx默認會自動安裝上很多模塊,能夠經過nginx -V
來查看本身的nginx安裝了什麼模塊,內置模塊不會顯示出來。
💡當你從我這裏學到了一個指令,但有疑問的時候,能夠考慮搜索一下官方文檔。看官方文檔是你應該學會的能力。nginx
1.從下載地址下載到nginx/Windows-x.x.x
,這個是面向win環境的。
2.下載到的是一個壓縮包,解壓出來,能夠看到以下的目錄結構,其中nginx.exe就是用來啓動nginx的程序
3.你能夠直接運行nginx.exe,而後訪問http://localhost/
,若是能看到下面的頁面,那麼表明安裝和啓動成功了。
web
.在linux下既能夠經過源代碼包來安裝(這裏不講,有興趣自行百度),也能夠經過其餘方式來安裝,例如redhat/centos就支持yum安裝,下面主要講使用yum來安裝nginx(💡yum方式安裝的話,自定義可能沒那麼強,但勝在方便,適合初學者,你能夠後面再學使用其餘方式安裝。yum模式安裝默認會按照額外的一些第三方模塊,但並無提供不少的第三方模塊安裝方法,安裝第三方模塊的時候還行建議使用編譯安裝的方式。但因爲咱們這裏沒有怎麼使用第三方模塊,因此暫時以yum方式爲例)。RHEL-CentOS nginx官方安裝文檔,咱們這裏只講centos7下的安裝,沒有講ubuntu下的安裝,須要的能夠自行看一下官方文檔或者百度一下。正則表達式
💡centos7下使用yum來安裝
1.執行sudo yum install yum-utils
2.vim /etc/yum.repos.d/nginx.repo
,填入如下內容,設置nginx的yum源:docker
[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true
3.執行一下yum repolist
,更新一下yum源:
數據庫
4.使用yum安裝nginx,yum install nginx
5.啓動nginx,systemctl start nginx
6.訪問http://linux系統IP/
,若是看到下面的圖就是安裝啓動成功。
💡防火牆默認防禦了80端口,可能你須要執行systemctl stop firewalld
來臨時關閉防火牆,這樣才能夠訪問。
json
1.docker pull nginx:1.18.0
【你也能夠自行去dockerhub看看你想安裝什麼版本】
2.docker images
,查看是否拉取鏡像成功:
3.docker run --name nginx-8080 -p 8080:80 -d nginx:1.18.0
【運行nginx,若是你使用docker運行nginx,那麼我默認當你有docker基礎了,這些命令就不介紹了。】
4.docker ps
查看nginx是否已經運行了:
5.訪問http://docker宿主機IP:8080/
,若是運行成功的話,會看到下圖:
ubuntu
🔵安裝成功以後,咱們簡單介紹一下nginx的目錄結構。
查看一下nginx安裝相關目錄:
[root@localhost ~]# whereis nginx nginx: /usr/sbin/nginx /usr/lib64/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz
🔵/etc/nginx/
就是nginx安裝的目錄:
名字 | 類型 | 說明 |
---|---|---|
conf.d | 目錄 | nginx主配置文件存儲位置 |
mime.types | 文件 | 設置Content-Type與擴展名的關係,例如能夠設置響應爲html文件時,響應的Content-Type爲text/html |
fastcgi_params scgi_params uwsgi_params |
文件 | 與fastcgi,scgi,uwsgi相關的配置文件 |
modules | 目錄 | nginx模塊目錄,nginx的模塊存儲在這裏,好比安裝第三方模塊的時候就存儲在這裏 |
nginx.conf | 文件 | nginx主配置文件 |
koi-utf koi-win win-utf |
文件 | 編碼轉換映射文件,用於在輸出內容到客戶端時,將一種編碼轉換到另外一種編碼。 由於做者是俄國人,因此有koi這個編碼轉換。 |
🔵/usr/sbin/nginx是nginx啓動程序
🔵/usr/lib64/nginx裏面放了模塊相關文件。
🔵/usr/share/nginx放了一些nginx的默認資源,好比index.html
🔵/usr/share/man/man8/nginx.8.gz存放了man語法幫助文件。
除了這些上面的文件/目錄,其實還有一些其餘的文件/目錄,咱們在後面教程中用到再講,好比/var/log/nginx
就是nginx默認的日誌存儲目錄。
------------------- 分割線:下面介紹簡單使用,因爲nginx很是少用於window,因此下面的例子基於linux -----------
下面我會簡單介紹一下默認的配置文件,並作一個很是簡單的修改,這將做爲後面的介紹nginx的基礎知識。
下面的配置文件我都有打註釋,若是你能看懂註釋(😓應該都能稍微看懂吧),那就記一下,若是看不懂,那就記一下變量的名字吧,這樣我後面介紹的時候你還記得這個變量寫在哪裏。
💡/etc/nginx/nginx.conf
:
💡/etc/nginx/conf.d/default.conf
:
在nginx.conf
中使用了include /etc/nginx/conf.d/*.conf;
來將conf.d下的文件導入到http塊中。
上面導入的server的效果等同於直接在http塊中寫server塊:
systemctl start nginx
。http://192.168.48.128
,你會看到一個welcome頁面。http://192.168.48.128
這個請求恰好匹配到了location /
,而返回的資源頁面其實恰好就是root+index獲得的路徑的內容,也就是/usr/share/nginx/html下的index.html
。Welcome to nginx!
修改爲Welcome to my nginx
,而後刷新一下,會看到頁面的效果變了。/usr/share/nginx/html下的index.html
。💡這個例子大概的給location匹配和資源返回開了個頭。
💡咱們嘗試修改一下location來使得可以訪問咱們本身建立的文件。也至關於驗證上面的例子的一些內容。
💡咱們在/usr/share/nginx/helloworld
下建立一個hello.html
<html> <body> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <h1>個人第一個標題</h1> <p>個人第一個段落。</p> </body> </html>
💡而後在conf.d/default.conf
增長一個location(直接與第一個location同級),location用於定義url匹配,作後端開發的可能更熟悉一個詞——路由分發,好比下面的location = /hello.html
就用於定義訪問nginx主機IP/hello.html
:
location = /hello.html { #root用於定義資源根目錄,好比訪問/hello.html獲得的是/usr/share/nginx/html/helloworld/hello.html root /usr/share/nginx/html/helloworld; }
訪問一下nginx主機IP/hello.html
就能夠看到咱們的內容,root用於定義根路徑,因此最終返回的文件的路徑是/usr/share/nginx/html/helloworld/hello.html
。
響應的是咱們定義的內容就說明咱們這個location配置成功了。
🤣這個例子可能沒什麼養分。但舉這個例子是爲了先讓讀者有參與感,能本身簡單地嘗試對nginx進行更改,給下面的location匹配和資源返回開個頭。
下面的內容介紹仍是須要一些基礎的nginx命令的,好比修改了配置信息以後須要檢查配置文件語法和重啓nginx之類的,因此這裏舉例一下基礎的nginx命令。
systemctl start nginx
:啓動nginxsystemctl restart nginx
:重啓nginx,修改配置文件須要重啓nginx,改資源文件不須要,nginx -s stop
: 關閉nginx程序,不保存相關信息nginx -s quit
:正常退出nginx,並保存相關信息。【quit的時候,Nginx在退出前會完成已經接受的鏈接請求,而stop不會。】nginx -s reload
:重啓nginx。nginx -V
:查看編譯參數。能夠用來查看安裝的模塊(不全的),模塊相關的事情,咱們後面再介紹,你暫時只須要知道nginx的不少功能都是基於模塊的,好比http_ssl模塊就負責nginx的https配置。nginx -v
能夠看到nginx的版本。nginx –t
檢查配置文件是否有語法錯誤。在每次重啓以前,都建議使用這個來檢查一下配置文件。否則關閉nginx以後不能快速重啓就糟糕了。nginx -h
查看簡單的幫助命令。nginx -c 主配置文件路徑
:以某個主配置文件爲基礎來運行nginx。💡咱們這裏介紹一下location的url匹配語法,從上面的helloworld的例子中,其實你能夠把location理解成一個請求映射。好比上面HelloWorld中咱們使用下面的這個location把nginx主機IP/hello.html
的訪問結果定義成/usr/share/nginx/html/helloworld/hello.html
的結果。
location = /hello.html { root /usr/share/nginx/html/helloworld; }
💡location經過url匹配把location內部定義的結果返回給請求者。好比說可使用return(直接返回,相似請求響應直接返回一個字符串),proxy_pass(代理服務器)等手段來定義返回的結果。若是不定義這些,就會基於路徑來嘗試訪問靜態的資源,因此上面的location纔會獲得/usr/share/nginx/html/helloworld/hello.html
的結果。
💡上面這個引出了很多東西,好比說return,好比說proxy_pass,但他們都與location有關,並且大可能是location內部的內容,因此這裏先簡單介紹一下location的url匹配語法,後面講location內部纔會講到return,proxy_pass這些知識點。
💡資源拼接問題:這裏先提早說一下省得看不懂下面的測試例子,有人疑惑只有root的話是怎麼找到應該返回的資源的。 若是使用非正則的location的話,會把location部分拼接到root指定的目錄後,好比上面的/usr/share/nginx/html/helloworld
+匹配結果/hello.html
就獲得了/usr/share/nginx/html/helloworld/hello.html
;若是是正則的,也會把匹配到的location部分拼接到root指定的目錄後。
loaction格式是location [=|~|~*|^~] pattern
,分紅三部分就是location, [=|~|~*|^~]
和pattern
,location固然是固定的寫法了,因此不須要介紹,咱們只介紹 [=|~|~*|^~]
和pattern
。
🔵[=|~|~*|^~]
部分的用法以下,注意,這部分是可選的,能夠沒有,沒有的話,此時狀況會不一樣,此時pattern不必定是正則:
= pattern
表明精確匹配pattern,此時pattern不是正則。*
好比location = /error
就只能匹配nginx主機IP/error
,不能匹配nginx主機IP/Error
,nginx主機IP/error01
^~
表明匹配以某個字符串開頭的url,此時pattern不是正則表達式
好比location ^~ /test
能夠匹配/test,/test001,/testAAA,/test/aaa
~ pattern
表明pattern這個正則匹配區分大小寫,pattern是一個正則,正則的內容咱們下面講。
~* pattern
表明pattern這個正則不區分大小寫,pattern是一個正則,正則的內容咱們下面講。
💡記清楚,哪些是正則,哪些不是。使用=
和^~
的不是正則,使用~
和~*
的是正則。
🔵pattern
部分語法遵循Linux正則表達式語法:
location = url
表明精確匹配url,url此時不被認爲是一個正則表達式,好比location = /hello.html
只精確匹配nginx主機IP/hello.html
,location = /
表明只匹配主機根目錄,也就是ip/。
location ^~ /pattern
表明匹配以某個字符串開頭的url,此時pattern不是正則表達式。
location /
表明通用匹配,由於全部的路徑都有/
做爲開頭。【這時候pattern也不算正則表達式】
location /pattern
表明匹配/pattern開頭的請求,此時pattern也不算正則,好比location /api/
匹配/api/
開頭的請求。但優先級比location [~|~*] pattern
低。
location [~|~*|^~] pattern
此時[~|~*|^~]
只是對正則表達式的大小寫區分的輔助標識,因此咱們下面針對Pattern來說解的時候能夠先忽視大小寫區分。pattern是一個正則表達式,咱們講一下它正則表達式的寫法。【nginx的正則表達式使用的是Linux的正則表達式規則】
字符 | 說明 | 額外說明 |
---|---|---|
$ |
用於限定結尾,好比location ~* .(gif|jpg|jpeg)$ 就是匹配任何以.gif、.jpg 或 .jpeg 結尾的請求 |
|
^ |
用於限定開頭,好比^error 能夠匹配error404 ,error500 ,不能匹配500error |
|
| |
知足其中之一便可,例如A|B 表明能夠匹配A,也能夠匹配B。 |
|
[] |
表明範圍,好比[0-9] 表明匹配0-9的數字,[a-z] 表明匹配a-z的字符。能夠同時有多個範圍,例如[a-zA-Z0-9] .若是範圍裏面使用^ ,那麼表明匹配除了範圍內的字符,好比[^0-9] 表明匹配0-9之外的字符。還能夠是[abc] ,這表明匹配字符a、b、c。🔴注意,a-9是不合法的範圍。 |
|
. |
表明匹配任意的一個字符 | |
? |
匹配前面的字符零次或一次 | |
+ |
匹配前面的字符一次或屢次 | |
* |
匹配前面的字符零次或屢次 | 貪婪模式與懶惰模式: 好比abcdabcd,若是是貪婪模式 a.*d ,匹配的結果是abcdabcd;若是是懶惰模式 a.*?d ,那麼是abcd,abcd |
{n} |
匹配前面的字符n次,必須是n次 | |
{n,} |
匹配前面的字符至少n次 | |
{n,m} |
匹配前面的字符,最少n次,最多m次。 | |
() |
用於劃分字符範圍 劃分字符範圍,好比 hello | hi Amy ,只會匹配出hello 和hi Amy ,而不是hello Amy ,劃分範圍以後(hello|hi) Amy 就能夠匹配到hello Amy 了。 |
|
\ |
用於轉義,好比. 表明匹配任意的一個字符,\. 就把. 變成了一個. ,這樣才能夠來匹配.html 這樣使用. 來作擴展名 |
|
\d |
表明匹配任意一個十進制數字,至關於[0-9] |
|
\D |
表明匹配任務一個非十進制數字 | |
\w |
表明匹配任意一個非符號字符,至關於[a-zA-Z0-9] |
|
\W |
表明匹配任意一個符號字符 | |
\s |
表明匹配任意一個空白字符。 | |
\S |
表明匹配任意一個非空白字符 |
學了上面的正則的意思,那你應該可以看懂下面的幾個正則了吧:
location ~ \.php$
:匹配以php結尾的請求。location ~* \.(gif|jpg|jpeg)$
匹配任何以.gif、.jpg 或 .jpeg 結尾的請求。location /api/
匹配/api/
開頭的請求。location /aaa/.*\.html$
表明匹配/aaa/
下後綴爲.html
的請求。location [=|~|~*|^~] @name
,用於內部跳轉,用於聲明一個pattern,http://nginx主機IP/hello2.html
若是發生找不到,那麼會顯示file not found
,由於這進行了一個內部跳轉,當發生404異常error_page 404 @file_err
的時候,會返回location @file_err
的響應,也就是上面定義的return 200 'file not found'
,return你能夠理解成直接返回定義的數據,200是響應碼。😓考慮到篇幅問題,不能給詳細例子,你們能夠基於上面的正則教程來自行測試。
當一個url能夠匹配多個規則的時候,核心優先級思想是匹配最精確的,實在沒有精確匹配的,再匹配模糊的,還有個最大前綴匹配的說法,在非正則表達式匹配的狀況下,發起/data/log/2
時,匹配的會是location /data/log
,而不是location /data
。
優先級是【注意url和pattern有區別,pattern表明正則表達式】:
(精確匹配)location = url
> (帶完整精確路徑的)location url
> (帶部分前綴路徑的)location ^~ prefix_url
>(模糊匹配的)location [~|~*] pattern
> location /pattern
> 通用匹配location /
舉個例子:好比有個請求http://192.168.31.128/hello/a
那麼下面的匹配順序是:
1.location = /hello/a
2.location /hello/a
3.location ^~ /hello
4.location ~ /hello
或location ~* /hello
5.location /hello
6.location /
💡測試上面這個例子的時候請兩兩測試。不要同時定義多個location。
server { listen 80; server_name localhost; default_type text/html; #location = /hello/a { # default_type text/html ; # return 200 'location = /hello/a'; #} #location ^~ /hello { # default_type text/html ; # return 200 'location ^~ /hello'; #} #location ~* ^/hello { # default_type text/html ; # return 200 'location ~* ^/hello'; #} # 這個並不能與其餘共存,會認爲重複了。但能夠與location /,location ~* ^/hello共存 location /hello { default_type text/html ; return 200 'location /hello'; } location / { default_type text/html ; return 200 'location /'; } #location /hello/a { # default_type text/html ; # return 200 'location /hello/a'; #} }
😓就算這裏給你介紹了匹配順序,但其實仍是不推薦搞那些容易混亂的匹配。
好比下面這種狀況:按上面的規則訪問http://192.168.31.128/hello/a
響應結果應該是location /hello/a
,但實際上並非,而是location ~* ^/hello
,而當你去掉location /hello/a
的時候,你又會發現結果變成了location ^~ /hello
😀location /pattern
和location [~|~*] pattern
單獨比較時,location [~|~*] pattern
的優先級比較高。
location ^~ /hello { default_type text/html ; return 200 'location ^~ /hello'; } location ~* ^/hello { default_type text/html ; return 200 'location ~* ^/hello'; } location /hello/a { default_type text/html ; return 200 'location /hello/a'; }
location內部能夠有不少指令,我這裏只介紹常見的。
上面的例子中,咱們大多都只定義了root、index和return ,咱們先來說root和index。
💡root用於指定網站的根目錄。
💡index指令用於設置網站的默認首頁。除了用在location,index還可使用在http、server塊中。起到在當前塊的全局配置默認首頁。
上面的測試,你可能會感到一種疑惑。
❓好比我定義了以下的location:
location / { root /usr/share/nginx/html; index index.html index.htm; }
但請求nginx主機IP/helloworld/hello.html
的時候返回/usr/share/nginx/html/helloworld/hello.html
,那麼是怎麼返回的呢?
首先nginx主機IP/helloworld/hello.html
在匹配了/
以後,匹配的剩餘部分helloworld/hello.html
會基於root來查找資源位置。
因此root + location獲得了最終的資源路由/usr/share/nginx/html/helloworld/hello.html
。
而直接訪問nginx主機IP/
時返回/usr/share/nginx/html/index.html
的內容這是由於index指令用於設置網站的默認首頁,root+index就是網站的默認首頁的資源文件/usr/share/nginx/html/index.html
。
💡root與alias
root和alias均可以用來定義網站的根目錄,但alias不會追加location匹配到的部分,好比下面的這個圖中location是能夠匹配http://192.168.48.131/helloworld/a.png
的,那麼使用root和alias時有什麼區別呢?
不基於正則的時候,使用http://192.168.48.131/test/a.png
來測試:
/usr/share/nginx/html/test/a.png
,會把匹配到的/
和test/a.png
追加到root指定的路徑以後。/usr/share/nginx/htmltest/a.png
,你會看到它並無攜帶上匹配的/
,而是把test/a.png
追加到了alias路徑以後。在location是正則表達式的時候,使用http://192.168.48.131/helloworld/helloworld/a.png
來測試:
/usr/share/nginx/html/helloworld/helloworld/a.png
,會把pattern部分直接追加到root指定的路徑以後。/usr/share/nginx/html/helloworld
,沒錯,就是alias的絕對路徑,它不會把正則表達式部分追加到alias指定的路徑以後。上面的時候有個例子我使用了return,return是能夠直接返回數據的。
💡一般使用return的時候還須要指定default_type,它用來定義當前返回的數據的類型,否則會默認當成下載流。會加在響應的Content-Type中。
語法格式以下:
return 響應碼 [響應的數據]
return 資源文件路徑
return 500;
上面的return的例子中,咱們大多都定義了一個default_type
指令,這是什麼呢?由於上面咱們是直接返回數據,與以前的返回html之類的資源文件不一樣,因此咱們須要指定返回的數據的類型,好比咱們返回的是一個json數據的時候,就指定default_type application/json;
。
默認的default_type
類型會是application/octet-stream
,若是咱們上面不設置default_type,這將致使咱們的響應變成下載流。【這個默認值是在nginx.conf中配置的】
❓爲何返回html之類的資源文件時不須要手動指定?
其實我以前也提過了(Helloworld的nginx.conf的註釋中),能夠參考nginx.conf
的include /etc/nginx/mime.types;
,這裏把mime.types中的類型映射導入了,好比text/html html htm shtml;
表明什麼意思呢?就是若是返回的文件格式是html
、htm
、shtml
,那麼default_type
就是text/html
。
🔵proxy_pass
用於設置被代理服務器的地址,能夠是主機名稱(https://www.baidu.com
這樣的)、IP地址(域名加端口號)的形式。
🔵proxy_pass
用於反向代理,參考下面的「反向代理」的內容。
location裏面還能夠放location,能夠繼續向下劃分。
deny和allow能夠用來限制用戶訪問,好比說某個內容,你只但願讓IP爲192.168.48.131
的可以訪問。而不讓其餘IP訪問,那麼可使用deny和allow來限制。(固然了,用if也能夠達到相似的效果,但可能會寫的沒那麼方便)
💡allow用於容許訪問
💡deny用於禁止訪問,默認會返回403 Forbidden。
💡allow和deny支持IP,CIDR(也就是這種192.168.10.0/24)和all
關鍵字,all表明所有。
💡當內部有多個規則時,💡自上而下判斷是否有權限,若是是deny all在前,後面的allow都沒用。有人會問,若是我配置了一個deny,不配置allow,那麼其餘的非deny的地址能夠訪問嗎?答案是能夠的,默認是放行的。
💡allow和deny能夠用在http
、server
、location
、limit_except
(limit_except是Http Core模塊的內容)中
❗測試deny和allow的時候不要和return一塊兒使用(但加個if之類進行判斷應該沒問題,總之不要在同一層),這兩個有點衝突,能夠說return優先級比較高。
location / { root /usr/share/nginx/html; deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; deny all; }
💡deny和allow是http_access模塊的內容。
💡你在訪問一些頁面的時候,你會發現他把整個文件目錄給你返回了。在nginx中可使用autoindex來達到這種效果。
💡若是設置了Index而且index文件存在(默認配置有Index,這表明你選定的root目錄不能有index.html),那麼默認首頁的不會autoindex。
💡使用指令autoindex on;
來開啓列出目錄的功能。
💡另外還能夠加上這兩個指令,autoindex_exact_size off;
表明顯示出文件的大小,單位是byte,默認是on,顯示精確大小,off表明顯示粗略大小,單位是kB/mB/GB(依文件大小而定);autoindex_localtime on;
用於顯示文件的建立時間,默認off是顯示GMT時間,換成on以後就顯示文件所在的服務器的時間。
大部分的內容都是location裏面的內容,這裏只簡單講講,後面根據需求再講了。