Nginx的誕生
Nginx (engine x) 是一個(gè)高性能的HTTP和反向代理服務(wù)器,也是一個(gè)IMAP/POP3/SMTP服務(wù)器。Nginx是由伊戈?duì)枴べ愃饕驗(yàn)槎砹_斯訪問量第二的Rambler.ru站點(diǎn)(俄文:Рамблер)開發(fā)的,第一個(gè)公開版本0.1.0發(fā)布于2004年10月4日。
將源代碼以類BSD許可證的形式發(fā)布,因它的穩(wěn)定性、豐富的功能集、示例配置文件和低系統(tǒng)資源的消耗而聞名。
Nginx是一款輕量級(jí)的Web 服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器,并在一個(gè)BSD-like 協(xié)議下發(fā)行。其特點(diǎn)是占有內(nèi)存少,并發(fā)能力強(qiáng),事實(shí)上nginx的并發(fā)能力確實(shí)在同類型的網(wǎng)頁服務(wù)器中表現(xiàn)較好,非常受中國(guó)很多互聯(lián)網(wǎng)公司青睞。
Nginx的常用功能
1、Http代理,反向代理
作為web服務(wù)器最常用的功能之一,尤其是反向代理。Nginx在做反向代理時(shí),提供性能穩(wěn)定,并且能夠提供配置靈活的轉(zhuǎn)發(fā)功能。Nginx可以根據(jù)不同的正則匹配,采取不同的轉(zhuǎn)發(fā)策略,比如圖片文件結(jié)尾的走文件服務(wù)器,動(dòng)態(tài)頁面走web服務(wù)器,只要你正則寫的沒問題,又有相對(duì)應(yīng)的服務(wù)器解決方案,你就可以隨心所欲的玩。并且Nginx對(duì)返回結(jié)果進(jìn)行錯(cuò)誤頁跳轉(zhuǎn),異常判斷等。如果被分發(fā)的服務(wù)器存在異常,他可以將請(qǐng)求重新轉(zhuǎn)發(fā)給另外一臺(tái)服務(wù)器,然后自動(dòng)去除異常服務(wù)器。
這個(gè)例子比較簡(jiǎn)單,中間只有一層代理的理想模型。真實(shí)的情況是中間會(huì)含有很多代理服務(wù)器的。
2、負(fù)載均衡
Nginx的負(fù)載均衡模塊目前支持4種調(diào)度算法,下面進(jìn)行分別介紹,其中后兩項(xiàng)屬于第三方調(diào)度算法。
(1)輪詢(默認(rèn))。每個(gè)請(qǐng)求按時(shí)間順序逐一分配到不同的后端服務(wù)器,如果后端某臺(tái)服務(wù)器宕機(jī),故障系統(tǒng)被自動(dòng)剔除,使用戶訪問不受影響。
Weight 指定輪詢權(quán)值,Weight值越大,分配到的訪問機(jī)率越高,主要用于后端每個(gè)服務(wù)器性能不均的情況下。
上圖的意思是,按照權(quán)值進(jìn)行分配,weight=2的服務(wù)器分配的并發(fā)請(qǐng)求比為2/2+3+4。以此類推其他服務(wù)器的并發(fā)請(qǐng)求分配比。
(2)ip_hash。每個(gè)請(qǐng)求按訪問IP的hash結(jié)果分配,這樣來自同一個(gè)IP的訪客固定訪問一個(gè)后端服務(wù)器,有效解決了動(dòng)態(tài)網(wǎng)頁存在的session共享問題。
當(dāng)192.168.0.2的用戶進(jìn)行訪問時(shí)隨機(jī)會(huì)調(diào)度到任何一個(gè)服務(wù)器上,當(dāng)訪問到IP1 的服務(wù)器上時(shí),以后再次求求訪問是將會(huì)繼續(xù)訪問IP1,相當(dāng)于用戶信息和服務(wù)器相互綁定。
(3)url_hash。此方法按訪問url的hash結(jié)果來分配請(qǐng)求,使每個(gè)url定向到同一個(gè)后端服務(wù)器,可以進(jìn)一步提高后端緩存服務(wù)器的效率。Nginx本身是不支持url_hash的,如果需要使用這種調(diào)度算法,必須安裝Nginx 的hash軟件包。
對(duì)于URL還會(huì)進(jìn)行模式匹配的問題,當(dāng)進(jìn)行URLhash 的時(shí)候會(huì)進(jìn)行模式匹配。
匹配規(guī)則為:
~:對(duì)URI做正則表達(dá)式模式匹配,區(qū)分字符大小寫;
~*:對(duì)URI做正則表達(dá)式模式匹配,不區(qū)分字符大小寫;
^~:對(duì)URI的左半部分做匹配檢查,不區(qū)分字符大小寫;
不帶符號(hào):精確匹配,以URI為前綴的所有uri;
Nginx之頁面緩存
Nginx可以對(duì)不同的文件做不同的緩存處理,配置靈活,并且支持FastCGI_Cache,主要用于對(duì)FastCGI的動(dòng)態(tài)程序進(jìn)行緩存。配合著第三方的ngx_cache_purge,對(duì)制定的URL緩存內(nèi)容可以的進(jìn)行增刪管理。
proxy_cache_path
語法:
proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];
默認(rèn)值:None
使用字段:http
指令指定緩存的路徑和一些其他參數(shù),緩存的數(shù)據(jù)存儲(chǔ)在文件中,并且使用代理url的哈希值作為關(guān)鍵字與文件名。levels參數(shù)指定緩存的子目錄數(shù),例如:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
文件名類似于:
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
levels指定目錄結(jié)構(gòu),可以使用任意的1位或2位數(shù)字作為目錄結(jié)構(gòu),如 X, X:X,或X:X:X 例如: “2”, “2:2”, “1:1:2“,但是最多只能是三級(jí)目錄。
所有活動(dòng)的key和元數(shù)據(jù)存儲(chǔ)在共享的內(nèi)存池中,這個(gè)區(qū)域用keys_zone參數(shù)指定。one指的是共享池的名稱,10m指的是共享池的大小。
注意每一個(gè)定義的內(nèi)存池必須是不重復(fù)的路徑,例如:
proxy_cache_path /data/nginx/cache/one levels=1 keys_zone=one:10m;
proxy_cache_path /data/nginx/cache/two levels=2:2 keys_zone=two:100m;
proxy_cache_path /data/nginx/cache/three levels=1:1:2 keys_zone=three:1000m;
proxy_cache
語法:proxy_cache zone_name;
默認(rèn)值:None
使用字段:http, server, location
設(shè)置一個(gè)緩存區(qū)域的名稱,一個(gè)相同的區(qū)域可以在不同的地方使用。
在0.7.48后,緩存遵循后端的”Expires”, “Cache-Control: no-cache”, “Cache-Control: max-age=XXX”頭部字段,0.7.66版本以后,”Cache-Control:“private”和”no-store”頭同樣被遵循。nginx在緩存過程中不會(huì)處理”Vary”頭,為了確保一些私有數(shù)據(jù)不被所有的用戶看到,后端必須設(shè)置 “no-cache”或者”max-age=0”頭,或者proxy_cache_key包含用戶指定的數(shù)據(jù)如$cookie_xxx,使用cookie的值作為proxy_cache_key的一部分可以防止緩存私有數(shù)據(jù),所以可以在不同的location中分別指定proxy_cache_key的值以便分開私有數(shù)據(jù)和公有數(shù)據(jù)。
緩存指令依賴代理緩沖區(qū)(buffers),如果proxy_buffers設(shè)置為off,緩存不會(huì)生效。
proxy_cache_valid
語法:
proxy_cache_valid reply_code [reply_code …] time;
默認(rèn)值:None
使用字段:http, server, location
為不同的應(yīng)答設(shè)置不同的緩存時(shí)間,例如:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
為應(yīng)答代碼為200和302的設(shè)置緩存時(shí)間為10分鐘,404代碼緩存1分鐘。
如果只定義時(shí)間:
proxy_cache_valid 5m;
那么只對(duì)代碼為200, 301和302的應(yīng)答進(jìn)行緩存。
同樣可以使用any參數(shù)任何應(yīng)答。
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
Nginx之URL重寫
URL重寫模塊(Rewrite)
這個(gè)模塊允許使用正則表達(dá)式重寫URI,并且可以根據(jù)相關(guān)變量重定向和選擇不同的配置。如果這個(gè)指令在server字段中指定,那么將在被請(qǐng)求的location確定之前執(zhí)行,如果在指令執(zhí)行后所選擇的location中有其他的重寫規(guī)則,那么它們也被執(zhí)行。如果在location中執(zhí)行這個(gè)指令產(chǎn)生了新的URI,那么location又一次確定了新的URI。這樣的循環(huán)可以最多執(zhí)行10次,超過以后nginx將返回500錯(cuò)誤。
break
語法:break
默認(rèn)值:none
使用字段:server, location, if
完成當(dāng)前設(shè)置的規(guī)則,停止執(zhí)行其他的重寫指令。
if
語法:if (condition) { … }
默認(rèn)值:none
使用字段:server, location
注意:在使用if指令之前請(qǐng)查看if is evil page并且盡量考慮用try_files代替。
判斷一個(gè)條件,如果條件成立,則后面的大括號(hào)內(nèi)的語句將執(zhí)行,相關(guān)配置從上級(jí)繼承。
可以在判斷語句中指定下列值:
一個(gè)變量的名稱;不成立的值為:空字符傳”“或者一些用“0”開始的字符串。
一個(gè)使用=或者!=運(yùn)算符的比較語句。
使用符號(hào)*和模式匹配的正則表達(dá)式:
~為區(qū)分大小寫的匹配。
~不區(qū)分大小寫的匹配(firefox匹配FireFox)。
!和!意為“不匹配的”。
使用-f和!-f檢查一個(gè)文件是否存在。
使用-d和!-d檢查一個(gè)目錄是否存在。
使用-e和!-e檢查一個(gè)文件,目錄或者軟鏈接是否存在。
使用-x和!-x檢查一個(gè)文件是否為可執(zhí)行文件。
正則表達(dá)式的一部分可以用圓括號(hào),方便之后按照順序用$1-$9來引用。
return
語法:return code
默認(rèn)值:none
使用字段:server, location, if
這個(gè)指令結(jié)束執(zhí)行配置語句并為客戶端返回狀態(tài)代碼,可以使用下列的值:204,400,402-406,408,410, 411, 413, 416與500-504。此外,非標(biāo)準(zhǔn)代碼444將關(guān)閉連接并且不發(fā)送任何的頭部。
rewrite
語法:rewrite regex replacement flag
默認(rèn)值:none
使用字段:server, location, if
按照相關(guān)的正則表達(dá)式與字符串修改URI,指令按照在配置文件中出現(xiàn)的順序執(zhí)行。
可以在重寫指令后面添加標(biāo)記。
如果替換的字符串以http://開頭,請(qǐng)求將被重定向,并且不再執(zhí)行多余的rewrite指令。
尾部的標(biāo)記(flag)可以是以下的值:
last - 完成重寫指令,之后搜索相應(yīng)的URI或location。
break - 完成重寫指令。
redirect - 返回302臨時(shí)重定向,如果替換字段用http://開頭則被使用。
permanent - 返回301永久重定向。
注意如果一個(gè)重定向是相對(duì)的(沒有主機(jī)名部分),nginx將在重定向的過程中使用匹配server_name指令的“Host”頭或者server_name指令指定的第一個(gè)名稱,如果頭不匹配或不存在,如果沒有設(shè)置server_name,將使用本地主機(jī)名,如果你總是想讓nginx使用“Host”頭,可以在server_name使用“*”通配符(查看http核心模塊中的server_name)。
rewrite_log
語法:rewrite_log on | off
默認(rèn)值:rewrite_log off
使用字段:server, location, if
變量:無
啟用時(shí)將在error log中記錄notice 標(biāo)記的重寫日志。
set
語法:set variable value
默認(rèn)值:none
使用字段:server, location, if
指令設(shè)置一個(gè)變量并為其賦值,其值可以是文本,變量和它們的組合。
你可以使用set定義一個(gè)新的變量,但是不能使用set設(shè)置$http_xxx頭部變量的值。
Nginx配置文件結(jié)構(gòu)
main block:主配置段,也即全局配置段;
event {
...
}:事件驅(qū)動(dòng)相關(guān)的配置;
http {
...
}:http/https 協(xié)議相關(guān)的配置段;
mail {
...
}
stream {
...
}
http協(xié)議相關(guān)的配置結(jié)構(gòu)
http {
...:各server的公共配置
server {
...
}:每個(gè)server用于定義一個(gè)虛擬主機(jī);
server {
...
listen
server_name
root
alias
location [OPERATOR] URL {
...
if CONDITION {
...
}
}
}
}
1、全局塊:配置影響nginx全局的指令。一般有運(yùn)行nginx服務(wù)器的用戶組,nginx進(jìn)程pid存放路徑,日志存放路徑,配置文件引入,允許生成worker process數(shù)等。
2、events塊:配置影響nginx服務(wù)器或與用戶的網(wǎng)絡(luò)連接。有每個(gè)進(jìn)程的最大連接數(shù),選取哪種事件驅(qū)動(dòng)模型處理連接請(qǐng)求,是否允許同時(shí)接受多個(gè)網(wǎng)路連接,開啟多個(gè)網(wǎng)絡(luò)連接序列化等。
3、http塊:可以嵌套多個(gè)server,配置代理,緩存,日志定義等絕大多數(shù)功能和第三方模塊的配置。如文件引入,mime-type定義,日志自定義,是否使用sendfile傳輸文件,連接超時(shí)時(shí)間,單連接請(qǐng)求數(shù)等。
4、server塊:配置虛擬主機(jī)的相關(guān)參數(shù),一個(gè)http中可以有多個(gè)server。
5、location塊:配置請(qǐng)求的路由,以及各種頁面的處理情況。
配置為文件詳解
#運(yùn)行用戶
user nginx;
#啟動(dòng)進(jìn)程,通常設(shè)置成和cpu的數(shù)量相等
worker_processes 1;
#全局錯(cuò)誤日志及PID文件
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
#工作模式及連接數(shù)上限
events {
use epoll;
#epoll是多路復(fù)用IO(I/O Multiplexing)中的一種方式,但是僅用于linux2.6以上內(nèi)核,可以大大提高nginx的性能
worker_connections 1024;#單個(gè)后臺(tái)worker process進(jìn)程的最大并發(fā)鏈接數(shù)
# multi_accept on;
}
#設(shè)定http服務(wù)器,利用它的反向代理功能提供負(fù)載均衡支持
http {
#設(shè)定mime類型,類型由mime.type文件定義
include /etc/nginx/mime.types;
default_type application/octet-stream;
#設(shè)定日志格式
access_log /var/log/nginx/access.log;
#sendfile 指令指定 nginx 是否調(diào)用 sendfile 函數(shù)(zero copy 方式)來輸出文件,對(duì)于普通應(yīng)用,
#必須設(shè)為 on,如果用來進(jìn)行下載等應(yīng)用磁盤IO重負(fù)載應(yīng)用,可設(shè)置為 off,以平衡磁盤與網(wǎng)絡(luò)I/O處理速度,降低系統(tǒng)的uptime.
sendfile on;
#tcp_nopush on;
#連接超時(shí)時(shí)間
#keepalive_timeout 0;
keepalive_timeout 60;
tcp_nodelay on;
#開啟gzip壓縮
gzip on;
#設(shè)定請(qǐng)求緩沖
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
#設(shè)定負(fù)載均衡的服務(wù)器列表
upstream mysvr {
#weigth參數(shù)表示權(quán)值,權(quán)值越高被分配到的幾率越大
#本機(jī)上的Squid開啟3128端口
server 192.168.8.1:3128 weight=5;
server 192.168.8.2:80 weight=1;
server 192.168.8.3:80 weight=6;
}
server {
#偵聽80端口
listen 80;
#定義使用www.xx.com訪問
server_name www.xx.com;
#設(shè)定本虛擬主機(jī)的訪問日志和日志格式
access_log logs/www.xx.com.access.log main;
#默認(rèn)請(qǐng)求
location / {
root /root; #定義服務(wù)器的默認(rèn)網(wǎng)站根目錄位置
index index.php index.html ; #定義首頁索引文件的名稱
fastcgi_pass www.xx.com;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
# 定義錯(cuò)誤提示頁面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /root;
}
#靜態(tài)文件,nginx自己處理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
root /var/www/virtual/htdocs;
#過期30天,靜態(tài)文件不怎么更新,過期可以設(shè)大一點(diǎn),如果頻繁更新,則可以設(shè)置得小一點(diǎn)。
expires 30d;
}
#PHP 腳本請(qǐng)求全部轉(zhuǎn)發(fā)到 FastCGI處理. 使用FastCGI默認(rèn)配置.
location ~ \.php$ {
root /root;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/www$fastcgi_script_name;
include fastcgi_params;
}
#設(shè)定查看Nginx狀態(tài)的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file conf/htpasswd;
}
#禁止訪問 .htxxx 文件
location ~ /\.ht {
deny all;
}
}
}