本文對Nginx進行了基本介紹,並描述了一些可以使用它完成的簡單任務。假設已經安裝了Nginx,如果沒有,請參閱“Nginx-簡介”。本博文介紹瞭如何啓動和停止Nginx以及重新加載其配置,解釋了配置文件的結構,並描述瞭如何設置Nginx以提供靜態內容,如何將Nginx配置爲代理服務器以及如何將其與FastCGI應用程序相連接。
啓動、停止和重新加載配置
nginx -s <signal>
signal
可以是以下信號之一:
- stop: 快速關機
- quit: 正常關機
- reload: 重新加載配置文件
- reopening: 重新打開日誌文件
如果要停止Nginx進程,等待工作進程完成當前請求,可以執行以下命令:
nginx -s quit
在諸如kill應用程序等Unix工具的幫助下,也可以向Nginx進程發送信號。在這種情況下,一個信號被直接發送到指定進程ID的進程。Nginx主進程的ID在默認情況下,被寫入在/usr/local/nginx/logs
或者/var/run
目錄下的nginx.pid
文件當中。如果Nginx的主進程ID爲1628,要發送退出信號,優雅的關閉Nginx,我們可以這樣:
nginx -s QUIT 1628
配置文件的結構
Nginx
由模塊組成,模塊由配置文件中指定的指定控制。指令分爲簡單指令和塊指令。一個簡單的指令由名稱和參數組成,用空格分割,以分號結束。塊指令具有與簡單指令相同的結構,但不是分號,而是一組由大括號包圍的附加指令。如果一個塊指令可以在大括號中包含其他指令,那麼它被稱爲上下文(例如:events、http、server和location)
任何放置在上下文外部的配置文件中的指令被認爲是在主上下文中。events
和http
指令駐留在主上下文中,server
駐留在http
當中,location
駐留在server
當中。
其中“#”後面都代表是註釋內容
頂級上下文有:
- events: 處理常規連接
- http: http請求
- mail: 郵件
- stream: TCP和UDP
在每個http
上下文中,都包含一個或多個server
塊來定義控制請求處理的虛擬服務器。對於http
上下文,每個server
指令控制對特定域或IP地址上的資源請求的處理。每個server
上下文中包含一個或多個location
塊來處理特定的Uri集。對於mail
或者stream
上下文,server
指令分別控制到達特定TCP端口或UNIX套接字的通信處理。
通常子上下文繼承父上下文中包含的指令的設置。一些指令可以出現在多個上下文當中,在這種情況之下,子上下文中的指令會覆蓋父上下文中的同名指令。
提供靜態內容
Web服務器的一項重要任務是分發文件。首先,我們先做一些準備工作,創建/user/image
目錄,並放置一個favorite.png
圖片。接下來,我們來修改一下/etc/nginx/sites-enabled
目錄下的default
文件(此文件安裝Nginx完後存在),在server
上下文中添加一個location
塊指令,如下:
location /image/ {
root /user;
}
修改保存之後,重啓Nginx。對於匹配的請求,會將URL添加到root
指定指定的路徑,即添加到/user
中,形成/user/image/
就是我們本地文件系統上所請求文件的路徑。我們在瀏覽器中訪問http://localhost/image/favorite.png
就能正確定位到圖片了!如果有多個location
塊,將匹配前綴最長的的那個!其中root
指令指定目錄!
如果某些功能無法正常工作,你可以查看/var/log/nginx/access.log
或/var/log/nginx/error.log
文件來查找原因!
設置簡單的代理服務器
Nginx的一個常見用法是將其設置爲代理服務器,這意味着服務器接收請求,將其傳遞給代理服務器,從代理服務器檢索響應並將其發送給客戶機。我們將配置一個基本的代理服務器,它使用本地目錄中的文件夾來處理圖像請求,並將所有請求發送到服務器中。在本例中,這兩個服務器定義在一個Nginx實例中,如下:
server {
listen 8080;
root /user/data;
location / {
index index.html;
}
}
這是一個簡單的服務器,它監聽端口8080(如果沒有指定listen
指令,將默認監聽80端口),並將所有的請求映射到本地文件系統上的/user/data
目錄。需先創建該目錄,並將index.html
文件放置在該目錄當中,否則請求將會引發404錯誤!
注意,當服務請求的location
塊不包含root
指令時,就會使用上下文中的root
指令!
下面,我們將修改一下配置,將成爲代理服務器配置,如下:
server {
listen 80;
location / {
proxy_pass http://localhost:8080;
}
location /image/ {
root /user;
}
}
在第一個location
塊中,使用proxy_pass
指令與參數中的協議、代理服務器的名稱和端口放在一起。我們還可以對location
做一些正則匹配,如下:
location ~ \.(png|jpg|gif)$ {
root /user;
}
如此,請求匹配所有以.gif
、.jpg
和.gif
結尾的Uri。正則表達式的前面應該加上~
,表示將使用正則表達式進行匹配!
設置FastCGI代理
Nginx可用於將請求路由到FastCGI
服務器,FastCGI
服務器運行各種框架和編程語言(如PHP)構建的應用程序。使用FastCGI
服務器最基本的Nginx配置包括使用fastcgi_pass
指令替代proxy_pass
指令,使用facgi_param
指令設置傳遞給FastCGI
服務器的參數。假設FastCGI
服務器可以在localhost:9000
上訪問。以上一節中的代理配置爲基礎,將fastcgi_pass
指令替代proxy_pass
指令,並將參數更改爲localhost:9000
。在PHP中,SCRIPT_FILENAME
參數用於確定腳本,QUERY_STRING
參數用於傳遞請求參數。配置如下:
server {
location / {
fastcgi_pass localhost:8080;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
location ~ \.(png|jgp|gif)$ {
root /user;
}
}
這將設置一個服務器,通過FastCGI
協議將靜態圖像請求外的所有請求路由到localhost:9000
上運行的代理服務器!
基於名稱的虛擬服務器
Nginx
首先確定哪個服務器應處理該請求,讓我們從一個簡單的配置開始,下面三個虛擬服務器都在監聽80端口,如下:
server {
listen 80;
server_name example.org www.example.org;
...
}
server {
listen 80;
server_name example.net www.example.net;
}
server {
listen 80;
server_name example.com www.example.com;
}
在上面配置當中,Nginx
只檢測請求的標頭字段“Host”以確定將請求路由到哪個服務器。如果其值與任何服務器都不匹配,或者請求根本不包含此標頭字段,則Nginx
會將請求路由到該端口的默認服務器。在上面的配置當中,默認服務器是第一個服務器,這是Nginx
的標準默認行爲。也可以在listen
指令中使用default_server
參數設置哪個服務器應該是默認的,如下:
server {
listen 80 default_server;
server_name example.net www.example.net;
}
值得注意的是,default_server
是偵聽端口的屬性,而不是服務器名稱的屬性。自0.8.21版本以來,default_server
就可以使用了,但是在更早的版本前,應使用default
參數
如何防止未定義的服務器名稱處理請求
如果不允許不帶“主機”標頭字段的請求,則可以定義僅丟棄請求的服務器:
server {
listen 80;
server_name "";
return 444;
}
在這裏,服務器名稱設置爲空字符串,該字符串將匹配沒有“Host”頭字段的請求,並且返回特殊的Nginx
的非標準代碼444,以關閉連接。自從版本0.8.48開始,這是服務器名稱的默認設置,因此server_name
可以省略。
基於名稱和基於IP的混合虛擬服務器
下面來看一個更爲複雜的配置,其中一些虛擬服務器偵聽不同的地址:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
}
在上面配置中,Nginx
首先根據server
塊的listen
指令檢測請求的IP地址和端口。然後,它根據與IP地址和端口匹配的server
塊的server_name
指令檢測請求的“Host”標頭字段。如果找不到服務器名稱,則默認服務器將處理該請求。例如,192.168.1.1:80
端口上接收到的請求將由192.168.1.1:80
端口的默認服務器(即第一臺服務器)處理。
一個簡單的PHP站點配置
現在讓我們看一下Nginx
處理一個典型的、簡單的PHP站點的請求,如下:
server {
listen 80;
server_name example.org www.example.org;
root /data/www;
location / {
index index.html index.php;
}
location ~* \.(png|jpg|gif)$ {
expires 30d;
}
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
無論列出的順序如何,Nginx
都會首先搜索文字字符串所給出的最特定的前綴location
。在上面的配置當中,唯一的前綴location
是“/”,因爲它匹配任何請求,所以它將被用作最後的手段。然後Nginx按照配置文件中列出的順序檢查正則表達式給出的location
。第一個匹配的表達式將停止搜索,Nginx
將使用這個location
。如果沒有正則表達式的匹配請求,則Nginx
使用前面找到的最特定的前綴的location
。
注意,所有類型的location
只檢測請求的Uri部分,沒有參數。這樣做是因爲查詢字符串中的參數可能以幾種方式給出,如下:
/index.php?user=john&page=1
/index.php?page=1&user=john
此外,任何人都可以在查詢字符串中請求任何東西:
/index.php?page=1&something+else&user=john
現在讓我們看一下上面配置中如何處理請求:
- 請求
logo.gif
首先與前綴location
“/”匹配,然後與正則表達式\.(png|jpg|gif)$
匹配,因此,請求由後一個location
匹配。使用僞指令root /data/www
將請求映射到文件/data/www/logo.gif
,然後將文件發送到客戶端 - 請求
index.php
也首先與前綴location
“/”匹配,然後與正則表達式\.php$
匹配。因此,請求由後一個location
匹配,並且請求被傳遞到了localhost:9000
上偵聽的FastCGI
服務器上。fastcgi_param
指令將FastCGI
參數SCRIPT_FILENAME
設置爲/data/www/index.php
,作爲FastCGI
的服務器執行文件。變量document_root
等同於root
指令的值,變量fastcgi_script_name
等同於請求的Uri,即index.php
. - 請求
about.html
僅與前綴location
“/”匹配,因此在該location
進行處理。使用僞指令root /data/www
將請求映射到文件/data/www/about.html
,然後將文件發送到客戶端 - 處理請求
/
更爲複雜,它僅與前綴location
“/”匹配,因此由該location
處理。然後index
指令根據其參數root /data/www
指令檢測文件的存在。如果文件/data/www/index.html
不存在,但是文件/data/www/index.php
存在,則該指令內部將重定向到index.php
,並且Nginx
將再次搜索location
,就好像請求是由客戶端發送的一樣。如前所述,重定向的請求最終將由FastCGI
服務器處理
在上面栗子當中,我們看到請求FastCGI
服務器時,需要使用fastcgi_pass
替代proxy_pass
,其中uwsgi
、SCGI
、memcached
或gRPC
服務也分別使用uwsgi_pass
、scgi_pass
、memcached_pass
和grpc_pass
指令替代proxy_pass
!