Nginx系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.htmlphp
nginx是一個優秀的web服務程序、反向代理程序。它採用非阻塞異步的套接字,使用epoll方式實現事件驅動,同時採用一個master+N個worker進程(默認)的方式處理請求,這種架構使得它在併發的處理能力上極其出色,能夠比較輕鬆地解決C10K問題。html
master進程用於管理worker進程,例如接收外界信號、向worker進程發送信號、銷燬worker進程、啓動worker進程等等。前端
nginx之因此性能良好,徹底是由它的架構決定的。每一個worker進程是業務處理進程,負責監聽套接字、處理請求、響應請求、代理請求至後端服務器等。nginx
做爲web server處理靜態資源時每一個worker進程的大體流程:web
(1).監聽套接字。
(2).與客戶端創建鏈接。
(3).處理監聽到的鏈接請求(加載靜態文件)。
(4).響應數據。
(5).斷開鏈接。 正則表達式
這幾個過程是每一個web server都具有的能力,但對於nginx來講,因爲它的異步非阻塞,每一個過程都不會阻塞(有些小過程必須阻塞的時候仍是會阻塞),使得併發處理能力很好。chrome
從監聽套接字開始說。每一個worker進程都是平等的,它們均可以去監聽套接字,正常狀況下不可避免地會形成爭搶和"驚羣問題",而nginx採用"爭搶"accept互斥鎖的方式,只有持有accept互斥鎖的worker進程纔有資格將鏈接請求接到本身的隊列中並完成TCP鏈接的創建。但每一個進程是相互獨立而平等的,誰有資格去"爭搶"互斥鎖且有更大概率爭搶成功?只要worker進程當前創建的鏈接數小於worker_connections指令指定的值(實際上源碼中設置的是該值的7/8),就容許爭搶互斥鎖,由於鏈接數超過了該值的7/8表示已經很是繁忙。除了繁忙程度限制資格,還有epoll_wait的timeout的指標,等待越久的worker進程爭搶能力越強。總之,在某一時刻,必定只有一個worker進程監聽並accept新的鏈接請求。apache
當已經監聽到鏈接請求時,worker進程與它進行三次握手,並最終accpet到本身的內存池中,並和客戶端交互數據,處理客戶端發送的http請求並響應數據給客戶端。可是,nginx的高效就在於它的異步非阻塞,不管是在TCP鏈接進入ESTABLISHED以前,仍是等待客戶端發送請求,亦或者是等待加載本地靜態資源的I/O,以及響應數據給客戶端的任意一個過程當中,nginx都是非阻塞的,在任意等待發生時均可以去處理其它事情。當等待的某個資源已經準備成功時將產生事件通知worker進程,worker進程可隨後去處理。在此過程當中,因爲worker進程綁定在一個CPU核心上(推薦如此作),全部的鏈接都放在內存池中,這使得上下文切換時是極其輕量的,極大地減輕了CPU消耗。從理論上來講,當每一個worker綁定了一個CPU核心時,它的併發處理能力主要依賴於內存的大小。後端
實際上apache httpd的event MPM也是異步非阻塞的,也能夠採用epoll,但它採用的是多線程方式,雖然異步,但它的異步彷佛不體如今併發能力上,而僅僅只是一些具備特殊狀態的鏈接(如長鏈接)的異步處理,在處理過程當中cpu仍是不斷地須要在各線程之間大量切換,併發能力並不比worker MPM強多少,相比nginx更是遠遠不如。瀏覽器
[root@xuexi nginx]# nginx -h
nginx version: nginx/1.12.0
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]
Options:
-?,-h : this help
-v : 輸出版本號
-V : 輸出版本號以及編譯選項
-t : 檢查配置文件的語法
-T : 檢查配置文件的語法並輸出配置的內容
-q : 靜默模式,不輸出任何信息
-s signal : 向主進程發送信號:stop, quit, reopen, reload
-p prefix : 設置nginx的basedir(默認爲編譯時的prefix)
-c filename : 指定配置文件
-g directives : 提早設置全局指令
-V
選項輸出編譯選項。
[root@xuexi nginx]# nginx -V
nginx version: nginx/1.12.0
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx-1.12.0 --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/subsys/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre
(1).使用默認配置文件直接啓動nginx和指定配置文件啓動nginx
nginx -c /usr/local/nginx/conf/nginx.conf
(2).運行時重載配置文件。當nginx主進程接收到重載配置文件的命令後,它會先檢查新配置文件語法,而後載入該配置文件到內存中並解析。而後,主進程fork一系列新的worker進程,併發送QUIT信號給舊的worker進程(graceful stop)。舊的工做進程接收到QUIT信號後,會中止接受新的鏈接請求,並繼續處理舊的鏈接直到請求處理完成後才退出。
nginx -s reload
(3).運行時快速關閉nginx。
nginx -s stop
(4).運行時優雅關閉nginx。全部的工做進程會中止接受新的鏈接,並繼續服務舊的鏈接請求直到全部的請求完成後才退出。
nginx -s quit
(5).運行時從新打開日誌文件。
ngnix -s reopen
Nginx的代碼由一個核心和一系列的模塊組成。
核心(core functionality)主要用於提供全局應用的基本功能,建立必要的運行時環境及確保不一樣模塊之間平滑地進行交互等,對應於配置文件的main段和event段。核心涉及的指令官方文檔:http://nginx.org/en/docs/ngx_core_module.html。
還有不少功能都經過模塊實現,nginx是高度模塊化程序。如web相關的功能模塊有"ngx_http_*_module",和mail相關的功能模塊有"ngx_mail_*_module",和tcp代理、負載均衡相關的功能模塊有"ngx_stream_*_module",這些類別的模塊中又分爲不少類別的模塊,如http類別的模塊中有基本核心模塊、事件類模塊、緩存類模塊、SSL相關模塊、負載均衡類模塊upstream等等。
如下是http功能模塊類中常見的模塊。
http類模塊名 | 模塊功能說明 | |
---|---|---|
ngx_http_core_module | http核心模塊,對應配置文件中的http段,包含不少指令,如location指令 | |
ngx_http_access_module | 訪問控制模塊,控制網站用戶對nginx的訪問,對應於配置文件中的allow和deny等指令 | |
ngx_http_auth_basic_module | 經過用戶名和密碼認證的訪問控制,如訪問站點時須要數據用戶名和密碼,指令包括auth_basic和auth_basic_user_file | |
ngx_http_charset_module | 設置網頁顯示字符集。指令之一爲charset,如charset utf-8 | |
ngx_http_fastcgi_module | fastcgi模塊,和動態應用相關。該模塊下有很是多的子模塊。 | |
ngx_http_flv_module | 支持flv視頻流的模塊,如邊下邊播 | |
ngx_http_mp4_module | 同flv模塊 | |
ngx_http_gzip_module | 壓縮模塊,用來壓縮nginx返回的響應報文。通常只壓縮純文本內容,由於壓縮比例很是大,而圖片等不會去壓縮 | |
ngx_http_image_filter_module | 和圖片裁剪、縮略圖相關模塊,須要安裝gd-devel才能編譯該模塊 | |
ngx_http_index_module | 定義將要被做爲默認主頁的文件,對應指令爲index。"index index.html,index.php" | |
ngx_http_autoindex_module | 當index指令指定的主頁文件不存在時,交給autoindex指令,將自動列出目錄中的文件autoindex {on/off} | |
ngx_http_log_module | 和訪問日誌相關的模塊,指令包括log_format和access_log | |
ngx_http_memcached_module | 和memcached相關的模塊,用於從memcached服務器中獲取相應響應數據 | |
ngx_http_proxy_module | 和代理相關,容許傳送請求到其它服務器 | |
ngx_http_realip_module | 當nginx在反向代理的後端提供服務時,獲取到真正的客戶端地址,不然獲取的是反向代理的IP地址 | |
ngx_http_referer_module | 實現防盜鏈功能的模塊 | |
ngx_http_rewrite_module | 和URL地址重寫相關的模塊,須要安裝pcre-devel才能編譯安裝該模塊 | |
ngx_http_scgi_module | simple cgi,是cgi的替代品,和fastcgi相似,但更簡單 | |
ngx_http_ssl_module | 提供ssl功能的模塊,即實現HTTPS | |
ngx_http_stub_status_module | 獲取nginx運行狀態信息 | |
ngx_http_upstream | 和負載均衡相關模塊 |
這些模塊共同組成了nginx的http功能。
nginx的配置文件有不少個,以下。其中主配置文件爲nginx.conf,其餘配置文件在須要的時候使用include指令將其包含到主配置文件中。
[root@xuexi ~]# ls /usr/local/nginx/conf/
fastcgi.conf fastcgi_params koi-utf mime.types nginx.conf scgi_params uwsgi_params win-utf
fastcgi.conf.default fastcgi_params.default koi-win mime.types.default nginx.conf.default scgi_params.default uwsgi_params.default
其中".default"後綴的是對應前綴配置文件的備份配置文件,".params"是對應前綴的參數文件。如fastcgi.conf是和fastcgi相關參數的配置文件,fastcgi.params是fastcgi的參數文件,fastcgi.conf.default是fastcgi.conf的備份文件。
關於主配置文件nginx.conf,因爲Nginx高度模塊化,因此它是分段配置的,核心模塊爲core,對應配置文件中的Main和Events段。此外還有其餘一些模塊。配置文件中每個指令必須以分號";"結束,不然語法錯誤。
Main用於配置錯誤日誌、進程及權限等相關的參數,Events用於配置IO模型,如epoll、kqueue、select或poll等,它們是必備模塊。以下配置:
#user nobody; # worker進程身份,默認使用編譯時指定值.語法爲"user user_name [group_name]"
worker_processes 4; # worker進程數量,該指令值依賴因素較多,例如是否CPU密集型、是否IO密集型。
# 在初始時設置爲cpu的總核數是一個不錯的選擇。
#error_log logs/error.log; # 錯誤日誌文件,禁用錯誤日誌"error_log /dev/null LEVEL;"
#error_log logs/error.log notice; # 級別:debug|info|notice|warn|error|crit|alert|emerg,默認爲error
#error_log logs/error.log info;
#pid logs/nginx.pid;
#lock_file logs/nginx.lock;
events {
worker_connections 1024; # 每一個worker進程的最大鏈接數
multi_accept on; # 是否一次性將監聽到的鏈接全接收進來,默認爲off,關閉時一次接收一條鏈接
accept_mutex on # 默認爲on,開啓時表示以串行方式接入新鏈接,不然將通報給全部worker。
# 這可能會浪費資源併產生不可預計的後果,例如驚羣問題
}
若是某個文件採用了相對路徑,則其相對的基準爲basedir。例如編譯時--prefix指定爲/usr/local/nginx,則指定pid爲logs/nginx.pid時,其實際路徑爲/usr/local/nginx/logs/nginx.pid。
worker_processes的值和work_connections的值決定了最大併發數量。例如上面的配置中,每一個worker進程最大容許1024個鏈接,配置了4個worker進程,因此併發數量爲1024*4=4096。但在反向代理場景中計算方法不一樣,由於nginx既要維持和客戶端的鏈接,又要維持和後端服務器的鏈接,所以處理一次鏈接要佔用2個鏈接,因此最大併發數計算方式爲:worker_processes*worker_connections/2。此外還需注意,除了和客戶端的鏈接、與後端服務器的鏈接,nginx可能還會打開其餘的鏈接,這些都會佔用文件描述符,從而影響併發數量的計算。最後還需注意,最大併發數量還受"容許打開的最大文件描述符數量"限制,可使用"worker_rlimit_nofile"指令修改或直接修改操做系統的對應內核參數。
能夠在main段使用worker_cpu_affinity指令綁定CPU核心。nginx經過位數識別CPU核心以及核心數,指定位數上佔位符爲1表示使用該核心,佔位符爲0表示不使用該核心。例如2核cpu的位數分別爲01和10,4核的位數分別爲1000,0100,0010以及0001,同理8核和16核。在結合worker_processes指令一塊兒使用時,要注意worker進程和核心的對應方式,例如:
# 每一個worker分別對應cpu0/cpu1/cpu2/cpu3
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
# 有4核心,但只有兩worker,第一個worker對應cpu0/cpu2,第二個worker對應cpu1/cpu3
worker_processes 2;
worker_cpu_affinity 0101 1010;
在events段,可使用"use"指令能夠指定使用哪一種I/O模型,Linux上默認是epoll,一般能夠不用手動去設置,由於nginx默認會採用最佳配置。
如下是main段和events段的配置示例,大多數採用的默認值,須要修改的大體就是worker數量、每一個worker最大鏈接數以及進程綁定cpu。
worker_processes 4;
events {
worker_connections 1024;
}
http段是由http相關模塊支持的。如下是默認配置項。注意,http根段下使用相對路徑是相對conf目錄的,如"include extra/.conf"表示的是conf/extra/.conf;非根段內的相對路徑如server段內使用相對路徑是相對於的安裝目錄<prefix>的,例如nginx安裝在/usr/local/nginx下,當location中的root設置爲html時,它表示的路徑是/usr/local/nginx/html/。
http {
include mime.types; # nginx支持的媒體文件類型。相對路徑爲同目錄conf下的其餘文件
default_type application/octet-stream; # 默認的媒體類型
#log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # 訪問日誌的格式
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on; # 啓用sendfile傳輸模式,此模式是"零拷貝"
#tcp_nopush on; # 只在sendfile on時有效。讓數據包擠滿到必定程度才發送出去,擠滿以前被阻塞
#keepalive_timeout 0; # keepalive的超時時間
keepalive_timeout 65;
#gzip on; # 是否啓用gzip壓縮響應報文
server { # 定義虛擬主機
listen 80; # 定義監聽套接字
server_name localhost; # 定義主機名加域名,即網站地址
#charset koi8-r; # 默認字符集
#access_log logs/host.access.log main; # 訪問日誌路徑
location / { # location容器,即URI的根
root html; # 站點根目錄,即DocumentRoot,相對路徑時爲<prefix>/html
index index.html index.htm; # 站點主頁文件
}
#error_page 404 /404.html; # 出現404 page not fount錯誤時,使用/404.html頁響應客戶端
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html; # 出現50x錯誤時,使用/50x.html頁返回給客戶端
location = /50x.html { # 定義手動輸入包含/50x.html時的location
root html;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
root指令設置站點根目錄,即httpd的documentroot,但又有所不一樣,由於nginx能夠在多個上下文位置處使用root指令,例如Location容器中。
若是配置以下:
location /i/ {
root /data/w3;
}
那麼nginx將使用文件/data/w3/i/top.gif響應請求"/i/top.gif"。
root指令僅僅只是將匹配的URI追加在root路徑後,若是要改變URI,應該使用alias指令,它會對URI進行替換。例如:
location /i/ {
alias /data/w3/images/;
}
那麼nginx將使用文件/data/w3/images/top.gif響應請求/i/top.gif。所以,若是alias指令的路徑最後一部分包含了URI,則最好使用root指令,而非alias指令,雖然它們都能成功響應。
location /images/ {
alias /data/w3/images/;
}
location /images/ {
root /data/w3/;
}
它們都能使用相對路徑,相對的是prefix。例如編譯路徑爲/usr/local/nginx,則"root html"指的是"/usr/local/nginx/html"。
與root和alias指令相關的變量爲$document_root、$realpath_root。其中$document_root的值便是root指令、alias指令的值,而$realpath_root的值是對root、alias指令進行絕對路徑換算後的值。
該指令對規範化後的URI進行匹配,並對匹配的路徑封裝一系列指令。 語法:
location [ = | ~ | ~* | ^~ ] uri { ... }
其中: location /uri/ {}:表示對/uri/目錄及其子目錄下的全部文件都匹配。因此"location / {}"的匹配範圍是最大的。
location = /uri/ {}:表示只對目錄或文件進行匹配,不對目錄中的文件和子目錄進行匹配。因此通常只用來作文件匹配
location ~ /uri/ {}:表示區分大小寫的正則匹配。
location ~* /uri/ {}:表示不區分大小寫的正則匹配。
location ^~ /uri/ {}:表示禁用正則匹配,即精確字符串匹配,此時正則中的元字符被解釋成普通字符。
它們的匹配優先級規則爲:nginx先檢查URI的前綴路徑,在這些路徑中找到最精確匹配請求URI的路徑。而後nginx按在配置文件中的出現順序檢查正則表達式路徑,匹配上某個路徑後即中止匹配並使用該路徑的配置,不然使用最大前綴匹配的路徑的配置。
使用"="前綴能夠定義URI和路徑的精確匹配。若是發現匹配,則終止路徑查找。例如請求"/"很頻繁,定義"location = /"能夠提升這些請求的處理速度,由於查找過程在第一次比較之後即結束。
如下是一個優先級的示例。
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
請求"/"能匹配A和B,但最精確匹配爲A。
請求"/index.html"的前綴"/"能匹配A和B,但A只能匹配"/"自身,所以最終匹配配置B。(前綴也能匹配E,但文件名沒法匹配)
請求"/documents/document.html"的前綴能匹配B和C,但C更精確,所以匹配配置C。(前綴也能匹配E,但文件名沒法匹配)
請求"/images/1.gif"的前綴能匹配B、D和E,且D和E都是最長路徑匹配,但^~優先級更高,所以匹配配置D。
請求"/documents/1.jpg"的前綴能匹配B、C,一樣也能匹配E,且E比B的匹配更精確,所以最終匹配配置E。
大體能夠將規則簡化爲以下優先級:
(location = uri ) > (location ^~ uri) > (location *~|~ uri) > (location uri)
即等號優先級最高,非正則匹配次之,再以後是正則匹配,它們之間有位置的前後順序,優先級最低的是沒有使用任何符號的匹配。
由此也能夠知道,"location / {}"這種方式是一種特殊的uri匹配,不管什麼uri路徑,都能往這裏面裝,能夠認爲它是默認匹配,當其它location都匹配不上時就會匹配它。
當出現對應狀態碼的錯誤時,指定返回的URI路徑。語法爲:
error_page code ... [=[response]] uri;
配置文件中的error_page部分默認爲:
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
上面的配置文件中,假如取消了404錯誤的error_page行註釋,當出現404錯誤時,其uri爲/404.html,而後會對其進行location的匹配,因爲只有"location / {}"能匹配到,因此它的目錄爲<prefix>/html/,即404.html文件路徑爲<prefix>/html/404.html。對於50x的error_page,其uri爲"/50x.html",因此會對其進行location匹配,發現能夠精確匹配到"location = /50x.html {}",固然"location / {}"也能匹配到,可是它的優先級更低,因此當出現50x錯誤時,將從<prefix>/html目錄下尋找50x.html,這裏正好和"location / {}"重複了,但它們的匹配過程是不同的。假如改成以下配置:
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /www/a.com/;
}
出現50x錯誤時,將返回/www/a.com/50x.html文件,而再也不是<prefix>/html/50x.html。
這兩個指令由ngx_http_access_module模塊提供,用於容許或限制某些IP地址的客戶端訪問。nginx中的allow和deny規則很簡單,從上向下匹配,只要匹配到就中止。例如:
allow 10.0.0.8
allow 192.168.100.0/24
deny all
容許10.0.0.8和192.168.100網段的訪問,其餘的都拒絕。
用於在響應首部中添加字段。例如:
server {
add_header RealPath $realpath_root;
}
將添加一個名爲RealPath的字段,值爲變量realpath_root的值。
[root@xuexi ~]# curl -I http://localhost/
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Tue, 17 Oct 2017 08:10:14 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 17 Oct 2017 03:20:10 GMT
Connection: keep-alive
ETag: "59e576ea-264"
RealPath: /usr/local/nginx-1.12.1/html # 此爲自定義添加字段
Accept-Ranges: bytes
nginx使用server容器定義一個虛擬主機。在nginx中,沒有嚴格區分基於IP和基於名稱的虛擬主機,它們經過listen指令和server_name指令結合起來造成不一樣的虛擬主機。
例如:
# 基於IP地址的虛擬主機
server {
listen 80;
server_name 192.168.100.25;
location / {
root /www/longshuai/;
index index.html index.htm;
}
}
server {
listen 80;
server_name 192.168.100.26;
location / {
root /www/xiaofang/;
index index.html index.htm;
}
}
# 基於名稱的虛擬主機
server {
listen 80;
server_name www.longshuai.com;
location / {
root /www/longshuai/;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.xiaofang.com;
location / {
root /www/xiaofang/;
index index.html index.htm;
}
}
# 基於端口的虛擬主機
server {
listen 80;
server_name 192.168.100.25;
location / {
root /www/longshuai/;
index index.html index.htm;
}
}
server {
listen 8080;
server_name 192.168.100.25;
location / {
root /www/xiaofang/;
index index.html index.htm;
}
}
其中server_name指令能夠定義多個主機名,第一個名字爲虛擬主機的首要主機名。例如:
server_name example.com www.example.com;
主機名中能夠含有星號("*"),以替代名字的開始部分或結尾部分(只能是起始或結尾,若是要實現中間部分的通配,可使用正則表達式)。例如"*.example.org"不只匹配www.example.org,也匹配www.sub.example.org。下面兩條指令是等價的。
server_name example.com *.example.com www.example.*;
server_name .example.com www.example.*;
也能夠在主機名中使用正則表達式,就是在名字前面補一個波浪線("~"):
server_name www.example.com ~^www\d+\.example\.com$;
nginx容許定義空主機名:
server {
listen 80;
server_name "";
return 444;
}
這種主機名可讓虛擬主機處理沒有"Host"首部的請求,而不是讓指定"地址:端口"的默認虛擬主機來處理,而這正是本指令的默認設置。即便用非默認的虛擬主機處理請求頭中不含"Host"字段的請求。通常這樣的請求處理方式是直接丟棄請求,並返回一個非標準的狀態碼來當即關閉鏈接,例如上面的444。
若是server塊中沒有定義server_name,nginx使用空名字做爲虛擬主機名。
經過名字查找虛擬主機時,若是一個名字能夠匹配多個指定的配置,好比同時匹配上通配符和正則表達式,按下面優先級,使用先匹配上的虛擬主機:
當開始接入請求時,(1)nginx首先判斷請求的套接字,即IP和端口號;(2)而後在listen套接字中選擇一個能匹配名稱的虛擬主機,若是沒有選出能匹配的名稱,則使用該套接字的默認虛擬主機。默認狀況下,監聽套接字的默認虛擬主機爲該套接字主機組中的第一個虛擬主機,但能夠經過listen指令的default_server屬性手動指定。
例以下面定義了4個虛擬主機:前3個都監聽在192.168.100.1:80上,第四個監聽在192.168.1.2:80上。
server {
listen 192.168.100.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.100.1:80 default_server;
server_name example.net www.example.net;
...
}
server {
listen 192.168.100.1:80;
server_name example.com www.example.com;
...
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
...
}
(1).從192.168.100.1:80上請求www.example.com,能匹配虛擬主機3,因而使用虛擬主機3的配置進行響應;
(2).從192.168.100.1:80上請求www.longshuai.com時,沒法匹配任何虛擬主機,因而使用默認虛擬主機2的配置進行響應。若是將listen的屬性default_server去掉,則使用虛擬主機1進行響應;
(3).從192.168.100.2:80上請求www.example.com時,使用虛擬主機4進行響應;
(4).從192.168.100.2:80上請求www.example.org時,因爲沒法匹配該套接字上的任何主機,因而使用默認虛擬主機響應,即虛擬主機4。
使用ngx_http_stub_status_module模塊提供的功能能夠獲取nginx運行的狀態信息。對應的指令只有一個,即stub_status。
例如,在某一個server下加上以下配置獲取該server的狀態信息。
server {
listen 80;
server_name www.longshuai.com;
location / {
root /www/longshuai/;
index index.html index.htm;
}
location /status {
stub_status on;
}
}
還能夠明確指定訪問該信息不記錄日誌,且提供訪問控制,不讓外界人隨意獲取信息。
location /status {
stub_status on;
access_log off;
allow 192.168.100.0/24;
deny all;
}
重載配置文件後,只需在瀏覽器中輸入"主機名/status"便可獲取信息。
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
狀態信息意義以下:
accepts:The total number of accepted client connections.
handled:The total number of handled connections. Generally, the parameter value is the same as accepts unless some resource limits have been reached (for example, the worker_connections limit).
requests:The total number of client requests.
log_format指定日誌的格式,語法以下:log\_format name string...;
。其中name指定日誌格式名稱,配置文件中name名稱不能重複。
如下是默認提供的main格式。
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
在main後面的是一堆變量,除了這些變量以外還有其餘不少變量可用,但如非特殊需求,默認的main格式就已經夠完美了。如下是變量的意義:
$remote_addr:客戶端的地址。若是nginx提供的web服務在後端,如前面有代理服務器或負載均衡等設備時,該變量只能獲取到前端的IP地址。此時要獲取到真正客戶端地址須要使用變量$http_x_forward_for,但要求前端服務器要開啓x_forward_for設置。
$http_x_forward_for:如上所述。
$remote_user:遠程客戶端用戶名稱。
$time_local:記錄訪問時間和時區信息。
$request:記錄用戶訪問時的url和http協議信息。如:"GET /favicon.ico HTTP/1.1"。
$status:記錄客戶端請求時返回的狀態碼,如成功的狀態碼爲200,page not found的狀態碼爲404。
$body_bytes_sent:記錄服務器響應給客戶端的主體大小。
$http_referer:記錄這次請求是從哪一個連接過來的,須要模塊ngx_http_referer_module支持,默認已裝,能夠防止倒鏈問題。
$http_user_agent:記錄客戶端的瀏覽器信息。如使用什麼瀏覽器發起的請求,是不是壓力測試工具在測試等。
例如,如下是默認格式的日誌信息。
192.168.100.27 - - [23/Apr/2017:23:08:56 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
192.168.100.27 - - [23/Apr/2017:23:08:56 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
192.168.100.27 - - [23/Apr/2017:23:08:56 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
192.168.100.27 - - [23/Apr/2017:23:08:56 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
192.168.100.1 - - [23/Apr/2017:23:08:56 +0800] "GET /status HTTP/1.1" 200 109 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.100.1 - - [23/Apr/2017:23:08:56 +0800] "GET /status HTTP/1.1" 200 109 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.100.1 - - [23/Apr/2017:23:08:56 +0800] "GET /status HTTP/1.1" 200 109 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.100.27 - - [23/Apr/2017:23:08:57 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
192.168.100.27 - - [23/Apr/2017:23:08:57 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
192.168.100.27 - - [23/Apr/2017:23:08:57 +0800] "GET /index.html HTTP/1.0" 200 17 "-" "ApacheBench/2.3"
access_log主要用於定義使用什麼格式的日誌,日誌存放路徑。語法以下:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
path指定路徑,path裏可使用變量。format指定日誌格式,不寫時或者配置文件中未配置access_log指令時,默認爲combined。buffer=size指定日誌緩衝區大小(默認64K),flush=time指定日誌刷盤的時間,if=condition指定某些條件,gzip=level指定日誌刷盤前先壓縮的壓縮級別(默認gzip=1)。
當指定了buffer或者gzip任意一個時,都會使用buffer先緩衝日誌,而後再刷盤。
例如
access_log /spool/logs/nginx-access.log gzip buffer=32k;
默認nginx不會自動分割日誌,也不支持在配置文件中使用cronolog以及rotatelogs(apache支持,由於支持管道傳遞)。要實現nginx的日誌分割,須要經過移動舊日誌、生成新日誌來實現。
mv old_log new_log
# 而後
nginx -s reload
# 或者
nginx -s reopen
# 或者
kill -s USR1 master_pid
pid能夠經過pid文件得到。
kill -s USR1 $(cat /var/run/nginx/nginx.pid)
要實現自動分割,須要使用腳本,並設置定時任務。
cat /usr/local/nginx/logs/cut_longhsuai.sh
#!/bin/bash
# cut the access log for www.longshuai.com
basedir=/usr/local/nginx
old_log_path=$basedir/logs/access.log
log_save_path=$basedir/logs
save_log_name=access_$(date -d "yesterday" +"%Y%m%d").log
[ -f "$old_log_path" ] || exit 1
/bin/mv $old_log_path $log_save_path/$save_log_name
$basedir/sbin/nginx -s reopen
再添加定時任務計劃。
chmod +x /usr/local/nginx/logs/cut_longshuai.sh
crontab -e
00 00 * * * /bin/sh /usr/local/nginx/logs/cut_longshuai.sh &>/dev/null
須要輸入用戶名和密碼才能訪問站點的功能爲web身份認證功能。nginx中由ngx_http_auth_basic_module模塊提供該功能。指令包括auth_basic和auth_basic_user_file。這兩個指令能夠在http根段、server段、location段使用。
auth_basic string | off
auth_basic_user_file path/to/user_passwd_file # 密碼文件使用相對路徑時是相對conf目錄的
passwd_file的格式爲:
user1:passwd1
user2:passwd2
須要注意的是,密碼文件不能使用明文密碼的方式。該類文件通常使用apache提供的工具htpasswd生成,該工具在httpd-tools包中,具體用法見htpasswd命令。也可使用openssl passwd生成相關密碼而後複製到密碼文件中。如下是一個示例:
server {
listen 80;
server_name www.longshuai.com www1.longshuai.com;
location / {
root /www/longshuai/;
index index.html index.htm;
auth_basic "Auth your name";
auth_basic_user_file /usr/local/nginx/htpasswd;
}
}
而後使用htpasswd生成密碼文件/usr/local/nginx/conf/htpasswd。
yum -y install httpd-tools htpasswd -b -c -m /usr/local/nginx/conf/htpasswd Jim 123456 htpasswd -b -m /usr/local/nginx/conf/htpasswd Tom 123456
-b
選項是表示batch模式,不用交互輸入密碼。-c
表示建立密碼文件,只能爲第一個用戶使用該選項,不然後面使用會覆蓋前面已經建立過的。-m
表示強制使用md5。Jim和Tom是須要驗證的用戶名,123456是密碼。查看生成的密碼文件。
[root@xuexi nginx]# cat htpasswd
Jim:$apr1$URdS8lcY$GyghBlYInlqfkto0ndnH1.
Tom:$apr1$B/orDxHj$1jIWk1X5XabpH3hcFQzoN1
而後重載配置文件,在瀏覽器中測試。測試時最好不要用IE。
也可使用openssl passwd生成,下面的"-apr1"(數值1而非字母L的小寫)選項是爲apache密碼作相關支持的。
openssl passwd -apr1 123456
$apr1$rD/3/kFH$L8KYfzAWFtHO8mOiR9dci1
# 或者加點鹽
openssl passwd -apr1 -salt 'xyz' 123456
$apr1$xyz$j0n99G44SENB4NmJiwEfJ0
而後將獲得的密碼複製到密碼文件中對應的用戶名後面便可。如將獲得的"$apr1$xyz$j0n99G44SENB4NmJiwEfJ0"做爲"Admin"用戶的驗證密碼。
Admin: $apr1$xyz$j0n99G44SENB4NmJiwEfJ0
https功能由ngx_http_ssl_module模塊提供。https鏈接的認證過程見SSL握手機制。簡單版的過程以下:
對於服務端而言,在配置https時,須要提供本身的數字證書用於發送給客戶端,還要提供本身的私鑰用於解密客戶端發送的預備主密鑰。當ssl鏈接創建完成後,後續鏈接要傳輸的數據都採用session key進行加密,但注意session key是對稱加密,客戶端和服務端是同樣的。
還需注意,在建立證書請求時,因爲須要指定common name,這是須要使用https的站點,所以每一個ssl證書只能爲一個server_name提供https服務。不過,經過特殊的配置方法,也能讓一個ssl證書服務於整個域名或域名內的某些主機。例如,https://www.baidu.com使用的證書就是頒發給"baidu.com"的,而不是該域名下的某一臺主機。如何實現這樣的功能,能夠網上搜索下關鍵字"ssl SubjectAltName",如有須要,我會另開一篇文章介紹實現方法。
如下是配置文件中默認的關於SSL相關的指令設置。
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
如下是創建https的相關過程:
cd /etc/pki/CA
(umask 077;openssl genrsa -out private/cakey.pem 2048)
openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650
touch index.txt
echo "01" > serial
(umask 077;openssl genrsa -out /usr/local/nginx/longshuai.key 2048)
openssl req -new -key /usr/local/nginx/longshuai.key -out /usr/local/nginx/longshuai.csr
openssl ca -in /usr/local/nginx/longshuai.csr -out longshuai.crt
mv longshuai.crt /usr/local/nginx/
此時,在/usr/local/nginx/目錄下就有了nginx本身的私鑰文件和證書文件。 [root@xuexi nginx]# ls longshuai*
longshuai.crt longshuai.csr longshuai.key
修改配置文件,配置ssl相關選項。
server {
listen 443 ssl;
server_name www.longshuai.com;
ssl_certificate /usr/local/nginx/longshuai.crt;
ssl_certificate_key /usr/local/nginx/longshuai.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
https://www.longshuai.com
測試。將會提示證書安全存在問題,說明配置成功。之後只要在客戶端安裝證書便可正常訪問。測試時,建議使用IE瀏覽器或使用IE內核的瀏覽器測試,這樣比較直觀。使用firefox、chrome等瀏覽器可能會由於是自建的CA而出現一些問題。