此文章配合 nginx配置文件解答 共同分享,了解。
一、nginx服務簡介
Nginx是一個高性能的HTTP和反向代理服務器
使用 Nginx 前必須了解的事項:
1)Nginx 本身只是一個 HTTP 和反向代理服務器
2)Nginx 支持簡單的負載均衡和容錯
3)支持作為基本 HTTP 服務器的功能
Nginx工作原理:
Nginx由內核和一系列模塊組成,內核提供web服務的基本功能,Nginx的各種功能和操作都由模塊來實現。Nginx的模塊從結構上分為核心模塊、基礎模塊和第三方模塊。
1)核心模塊: HTTP模塊、EVENT模塊和MAIL模塊
2)基礎模塊: HTTP Access模塊、HTTP FastCGI模塊、HTTP Proxy模塊和HTTP Rewrite模塊
3)第三方模塊: HTTP Upstream Request Hash模塊、Notice模塊和HTTP Access Key模塊及用戶自己開發的模塊
如果需要增加或刪除模塊,需要重新編譯Nginx,
如果有需要動態加載模塊,可以使用由淘寶網發起的web服務器Tengine,在nginx的基礎上增加了很多高級特性,完全兼容Nginx,已被國內很多網站采用。
Nginx處理連接過程:
Nginx的工作模式很簡單,就是采用一個master進程和多個worker工作進程:
master:
當 nginx 在啟動后,會有一個 master 進程和多個 worker 進程。master進程主要用來管理worker進程,master 要做的就是:接收來自外界的信號,向各 worker 進程發送信號,監控 worker 進程的運行狀態,當 worker 進程退出后(異常情況下),會自動重新啟動新的 worker 進程。
主要完成如下工作:
1)讀取並驗證配置信息;
2)創建、綁定及關閉套接字;
3)啟動、終止 worker 進程及維護 worker 進程的個數;
4)無須中止服務而重新配置工作;
5)控制非中斷式程序升級,啟用新的二進制程序並在需要時回滾至老版本;
6)重新打開日志文件;
7)編譯嵌入式perl腳本
worker:
對於基本的網絡事件,則是放在 worker 進程中來處理了。多個 worker 進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個 worker 進程中處理,一個 worker 進程,不可能處理其它進程的請求(一對一)。然而 nginx 沒有專門地仲裁或連接分布的 worker,這項工作是由操作系統內核機制完成的。在啟動時,創建一組初始的監聽套接字,HTTP 請求和響應之時,worker 連續接收、讀取和寫入套接字。
worker 進程主要完成的任務包括:
1)接收、傳入並處理來自客戶端的連接;
2)提供反向代理及過濾功能;
3)nginx任何能完成的其它任務
異步非阻塞
異步的概念是和同步相對的,也就是不同事件之間不是同時發生的。非阻塞的概念是和阻塞對應的,阻塞是事件按順序執行,每一事件都要等待上一事件的完成,而非阻塞是如果事件沒有准備好,這個事件可以直接返回,過一段時間再進行處理詢問,這期間可以做其他事情。
二、nginx相對於傳統的apache服務的優缺點
apache有自帶php解析功能(apache環境部署好后,不需要再啟動php服務,apache自動解析php文件,機器上只要有php命令即可;但是nginx不行,nginx必須結合php服務才能解析php文件,兩則服務都要啟動)
存在就是理由,一般來說,需要性能的web 服務,用nginx 。
如果不需要性能只求穩定,那就用apache。
后者的各種功能模塊實現得比前者,例如ssl 的模塊就比前者好,可配置項多。
這里要注意一點,epoll(freebsd 上是 kqueue )網絡IO 模型是nginx 處理性能高的根本理由,但並不是所有的情況下都是epoll 大獲全勝的,如果本身提供靜態服務的就只有寥寥幾個文件,apache 的select 模型或許比epoll 更高性能。當然,這只是根據網絡IO 模型的原理作的一個假設,真正的應用還是需要實測了再說的。
2)作為 Web 服務器:相比 Apache,Nginx 使用更少的資源,支持更多的並發連接,體現更高的效率,這點使 Nginx 尤其受到虛擬主機提供商的歡迎。在高連接並發的情況下,Nginx是Apache服務器不錯的替代品: Nginx在美國是做虛擬主機生意的老板們經常選擇的軟件平台之一. 能夠支持高達 50,000 個並發連接數的響應, 感謝Nginx為我們選擇了 epoll and kqueue 作為開發模型.
Nginx作為負載均衡服務器: Nginx 既可以在內部直接支持 Rails 和 PHP 程序對外進行服務, 也可以支持作為 HTTP代理 服務器對外進行服務. Nginx采用C進行編寫, 不論是系統資源開銷還是CPU使用效率都比 Perlbal 要好很多.
作為郵件代理服務器: Nginx 同時也是一個非常優秀的郵件代理服務器(最早開發這個產品的目的之一也是作為郵件代理服務器), Last.fm 描述了成功並且美妙的使用經驗.
Nginx 是一個安裝非常的簡單 , 配置文件非常簡潔(還能夠支持perl語法), Bugs 非常少的服務器: Nginx 啟動特別容易, 並且幾乎可以做到7*24不間斷運行,即使運行數個月也不需要重新啟動. 你還能夠不間斷服務的情況下進行軟件版本的升級 .
3)Nginx 配置簡潔,Apach復雜;Nginx靜態處理性能比Apache高3倍以上;Apache對PHP支持比較簡單,Nginx需要配合其他后端用;Apache的組件比Nginx多;
4)最核心的區別在於apache是同步多進程模型,一個連接對應一個進程;nginx是異步的,多個連接(萬級別)可以對應一個進程
5)nginx處理靜態文件好,耗費內存少.但apache目前也有它的優勢,有很多豐富的特性.所以還需要搭配着來.當然如果能確定nginx就適合需求,那么使用nginx會是更經濟的方式.
6)從個人過往的使用情況來看,nginx的負載能力比apache高很多。最新的服務器也改用nginx了。而且nginx改完配置能-t測試一下配置有沒有問題,apache重啟的時候發現配置出錯了,會很崩潰,改的時候都會非常小心翼翼現在看有好多集群站,前端nginx抗並發,后端apache集群,配合的也不錯。
7)一般動態請求要apache去做,nginx只適合靜態和反向。
8)從個人經驗來看,nginx是很不錯的前端服務器,負載性能很好,linux服務器上運營nginx,用webbench模擬10000個個靜態文件請求毫不吃力。apache對php等語言的支持很好,此外apache有強大的支持網路,反正時間相對nginx更久,bug少,但是apache有先天不支持多核心處理負載雞肋的缺點,所以建議使用nginx做前端,后端用apache。大型網站建議用nginx自代的集群功能!
9)Nginx優於apache的主要兩點還體現在:Nginx本身就是一個反向代理服務器;Nginx支持7層負載均衡;其他的當然,Nginx可能會比apache支持更高的並發;Aapche因為其成熟的技術和開發社區,總體來說也有非常不錯的性能,很多大公司而言還比較青睞apache。
10)你對web server的需求決定你的選擇。大部分情況下nginx都優於apache,比如說靜態文件處理、PHP-CGI的支持、反向代理功能、前端Cache、維持連接等等。在Apache+PHP(prefork)模式下,如果PHP處理慢或者前端壓力很大的情況下,很容易出現Apache進程數飆升,從而拒絕服務的現象。
11)對於nginx,我喜歡它配置文件寫的很簡潔,正則配置讓很多事情變得簡單運行效率高,占用資源少,代理功能強大,很適合做前端響應服務器
12)Apache在處理動態有優勢,Nginx並發性比較好,CPU內存占用低,如果rewrite頻繁,那還是Apache更好。
常用的 Nginx 參數和控制
Nginx 安裝后只有一個程序文件,本身並不提供各種管理程序,它是使用參數和系統信號機制對 Nginx 進程本身進行控制的。 Nginx 的參數包括有如下幾個:
-c <path_to_config>:使用指定的配置文件而不是 conf 目錄下的 nginx.conf 。
-t:測試配置文件是否正確,在運行時需要重新加載配置的時候,此命令非常重要,用來檢測所修改的配置文件是否有語法錯誤。
-v:顯示 nginx 版本號。
-V:顯示 nginx 的版本號以及編譯環境信息以及編譯時的參數。
例如我們要測試某個配置文件是否書寫正確,我們可以使用以下命令
sbin/nginx – t – c conf/nginx2.conf
當一台服務器中啟用多個實例的nginx時(即開啟不同端口的nginx),那么啟動nginx的時候就要根據各自的nginx配置文件進行啟動了,
/data/nginx/sbin/nginx -c /data/nginx/conf/nginx.conf
/data/nginx1.9/sbin/nginx -c /data/nginx1.9/conf/nginx.conf
/opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
有兩種方式來通過這些信號去控制Nginx:
第一是通過logs目錄下的nginx.pid查看當前運行的Nginx的進程ID,通過 kill – XXX <pid> 來控制 Nginx,其中 XXX 就是上表中列出的信號名。
如果系統中只有一個Nginx進程,那也可以通過 killall 命令來完成,例如運行 killall – s HUP nginx 來讓 Nginx 重新加載配置。
配置 Nginx
先來看一個實際的配置文件:
user www;# 工作進程的屬主 worker_processes 4;# 工作進程數,一般與 CPU 核數等同 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { use epoll;#Linux 下性能最好的 event 模式 worker_connections 2048;# 每個工作進程允許最大的同時連接數 } http { include mime.types; 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 off; access_log logs/access.log;# 日志文件名 sendfile on; #tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; include gzip.conf; # 集群中的所有后台服務器的配置信息 upstream tomcats { server 192.168.0.11:8080 weight=10; server 192.168.0.11:8081 weight=10; server 192.168.0.12:8080 weight=10; server 192.168.0.12:8081 weight=10; server 192.168.0.13:8080 weight=10; server 192.168.0.13:8081 weight=10; } server { listen 80;#HTTP 的端口 server_name localhost; charset utf-8; #access_log logs/host.access.log main; location ~ ^/NginxStatus/ { stub_status on; #Nginx 狀態監控配置 access_log off; } location ~ ^/(WEB-INF)/ { deny all; } location ~ \.(htm|html|asp|php|gif|jpg|jpeg|png|bmp|ico|rar|css|js| zip|java|jar|txt|flv|swf|mid|doc|ppt|xls|pdf|txt|mp3|wma)$ { root /opt/webapp; expires 24h; } location / { proxy_pass http://tomcats;# 反向代理 include proxy.conf; } error_page 404 /html/404.html; # redirect server error pages to the static page /50x.html # error_page 502 503 /html/502.html; error_page 500 504 /50x.html; location = /50x.html { root html; } } }
Nginx 監控
上面是一個實際網站的配置實例,其中#號后面的文字為配置說明。
上述配置中,首先我們定義了一個 location ~ ^/NginxStatus/,這樣通過 http://localhost/NginxStatus/ 就可以監控到 Nginx 的運行信息,顯示的內容如下:
Active connections: 70
server accepts handled requests
14553819 14553819 19239266
Reading: 0 Writing: 3 Waiting: 67
NginxStatus 顯示的內容意思如下:
active connections – 當前 Nginx 正處理的活動連接數。
server accepts handled requests -- 總共處理了 14553819 個連接 , 成功創建 14553819 次握手 ( 證明中間沒有失敗的 ), 總共處理了 19239266 個請求 ( 平均每次握手處理了 1.3 個數據請求 )。
reading -- nginx 讀取到客戶端的 Header 信息數。
writing -- nginx 返回給客戶端的 Header 信息數。
waiting -- 開啟 keep-alive 的情況下,這個值等於 active - (reading + writing),意思就是 Nginx 已經處理完正在等候下一次請求指令的駐留連接。
靜態文件處理
通過正則表達式,我們可讓 Nginx 識別出各種靜態文件,例如 images 路徑下的所有請求可以寫為:
location ~ ^/images/ {
root /opt/webapp/images;
}
而下面的配置則定義了幾種文件類型的請求處理方式。
location ~ \.(htm|html|gif|jpg|jpeg|png|bmp|ico|css|js|txt)$ {
root /opt/webapp;
expires 24h;
}
對於例如圖片、靜態 HTML 文件、js 腳本文件和 css 樣式文件等,我們希望 Nginx 直接處理並返回給瀏覽器,這樣可以大大的加快網頁瀏覽時的速度。因此對於這類文件我們需要通過 root 指令來指定文件的存放路徑,同時因為這類文件並不常修改,通過 expires 指令來控制其在瀏覽器的緩存,以減少不必要的請求。 expires 指令可以控制 HTTP 應答中的“ Expires ”和“ Cache-Control ”的頭標(起到控制頁面緩存的作用)。您可以使用例如以下的格式來書寫 Expires:
expires 1 January, 1970, 00:00:01 GMT;
expires 60s;
expires 30m;
expires 24h;
expires 1d;
expires max;
expires off;
動態頁面請求處理
Nginx 本身並不支持現在流行的 JSP、ASP、PHP、PERL 等動態頁面,但是它可以通過反向代理將請求發送到后端的服務器,例如 Tomcat、Apache、IIS 等來完成動態頁面的請求處理。前面的配置示例中,我們首先定義了由 Nginx 直接處理的一些靜態文件請求后,其他所有的請求通過 proxy_pass 指令傳送給后端的服務器(在上述例子中是 Tomcat)。最簡單的 proxy_pass 用法如下:
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
}
這里我們沒有使用到集群,而是將請求直接送到運行在 8080 端口的 Tomcat 服務上來完成類似 JSP 和 Servlet 的請求處理。
當頁面的訪問量非常大的時候,往往需要多個應用服務器來共同承擔動態頁面的執行操作,這時我們就需要使用集群的架構。 Nginx 通過 upstream 指令來定義一個服務器的集群,最前面那個完整的例子中我們定義了一個名為 tomcats 的集群,這個集群中包括了三台服務器共 6 個 Tomcat 服務。而 proxy_pass 指令的寫法變成了:
location / {
proxy_pass http://tomcats;
proxy_set_header X-Real-IP $remote_addr;
}
在 Nginx 的集群配置中,Nginx 使用最簡單的平均分配規則給集群中的每個節點分配請求。一旦某個節點失效時,或者重新起效時,Nginx 都會非常及時的處理狀態的變化,以保證不會影響到用戶的訪問。
^~ 開頭表示uri以某個常規字符串開頭,理解為匹配 url路徑即可。nginx不對url做編碼,因此請求為/static/20%/aa,可以被規則^~ /static/ /aa匹配到(注意是空格)。
~ 開頭表示區分大小寫的正則匹配
~* 開頭表示不區分大小寫的正則匹配
!~和!~* 分別為區分大小寫不匹配及不區分大小寫不匹配 的正則
/ 通用匹配,任何請求都會匹配到。
多個location配置的情況下匹配順序為(參考資料而來,還未實際驗證,試試就知道了,不必拘泥,僅供參考):
首先匹配 =,其次匹配^~, 其次是按文件中順序的正則匹配,最后是交給 / 通用匹配。當有匹配成功時候,停止匹配,按當前匹配規則處理請求。
示例說明:
有如下匹配規則:
location = / {
#規則A
}
location = /login {
#規則B
}
location ^~ /static/ {
#規則C
}
location ~ \.(gif|jpg|png|js|css)$ {
#規則D
}
location ~* \.png$ {
#規則E
}
location !~ \.xhtml$ {
#規則F
}
location !~* \.xhtml$ {
#規則G
}
location / {
#規則H
}
產生的效果如下:
訪問根目錄/, 比如http://localhost/ 將匹配規則A
訪問http://localhost/login 將匹配規則B,http://localhost/register 則匹配規則H
訪問http://localhost/static/a.html 將匹配規則C
訪問http://localhost/a.gif, http://localhost/b.jpg 將匹配規則D和規則E,但是規則D順序優先,規則E不起作用, 而 http://localhost/static/c.png 則優先匹配到 規則C
訪問http://localhost/a.PNG 則匹配規則E, 而不會匹配規則D,因為規則E不區分大小寫。
訪問http://localhost/a.xhtml 不會匹配規則F和規則G,http://localhost/a.XHTML不會匹配規則G,因為不區分大小寫。規則F,規則G屬於排除法,符合匹配規則但是不會匹配到,所以想想看實際應用中哪里會用到。
訪問http://localhost/category/id/1111 則最終匹配到規則H,因為以上規則都不匹配,這個時候應該是nginx轉發請求給后端應用服務器,比如FastCGI(php),tomcat(jsp),nginx作為方向代理服務器存在。
所以實際使用中,至少有三個匹配規則定義,如下:
直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。
這里是直接轉發給后端應用服務器了,也可以是一個靜態首頁
第一個必選規則
location = / {
proxy_pass http://tomcat:8080/index
}
第二個必選規則是處理靜態文件請求,這是nginx作為http服務器的強項
有兩種配置模式,目錄匹配或后綴匹配,任選其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三個規則就是通用規則,用來轉發動態請求到后端應用服務器
非靜態文件請求就默認是動態請求,自己根據實際把握
畢竟目前的一些框架的流行,帶.php,.jsp后綴的情況很少了
location / {
proxy_pass http://tomcat:8080/
}
Nginx官方提供的各種功能模塊應有盡有,結合這些模塊可以完整各種各樣的配置要求,例如:壓縮、防盜鏈、集群、FastCGI、流媒體服務器、Memcached 支持、URL 重寫等等,更關鍵的是Nginx擁有Apache和其他HTTP服務器無法比擬的高性能。甚至可以在不改變原有網站的架構上,通過在前端引入Nginx做負載均衡來提升網站的訪問速度。
一,在nginx中配置proxy_pass時的加不加/的問題 要注意proxy_pass后的url最后的/ 當加上了/,相當於是絕對根路徑,則nginx不會把location中匹配的路徑部分代理走 如果沒有/,則會把匹配的路徑部分也給代理走 例: location ^~ /static_js/ { proxy_cache js_cache; proxy_set_header Host js.test.com; proxy_pass http://js.test.com/; } 如上面的配置,如果請求的url是http://servername/static_js/test.html 會被代理成http://js.test.com/test.html 而如果這么配置 例: location ^~ /static_js/ { proxy_cache js_cache; proxy_set_header Host js.test.com; proxy_pass http://js.test.com; } 如上面的配置,如果請求的url是http://servername/static_js/test.html 則會被代理到http://js.test.com/static_js/test.htm
二,關於proxy_pass配置的uri問題 你不想nginx對你的URI請求有任何形式的修改,那么,proxy_pass的配置中就不應該有任何URI部分。 舉個例子,nginx服務器IP為10.0.0.20,它的配置不含URI: location /firstcond/ { proxy_pass http://10.0.0.30:90; } 那么, 原:http://10.0.0.20/first/second/test.html 轉:http://10.0.0.30:90/first/second/test.html 如果配置成含URI: location /firstcond/ { proxy_pass http://10.0.0.30:90/myuri; } 那么, 原: http://10.0.0.20/first/second/test.html 轉:http://10.0.0.30:90/myuri/test.html 簡單地說,配置了URI之后,跳轉行為可能會令你感到莫名其妙。
********************************************************************************************************************************
nginx的全局變量
remote_addr 客戶端ip,如:192.168.4.2
binary_remote_addr 客戶端ip(二進制)
remote_port 客戶端port,如:50472
remote_user 已經經過Auth Basic Module驗證的用戶名
host 請求主機頭字段,否則為服務器名稱,如:dwz.stamhe.com
request 用戶請求信息,如:GET /?_a=index&_m=show&count=10 HTTP/1.1
request_filename 當前請求的文件的路徑名,由root或alias和URI request組合而成,如:/webserver/htdocs/dwz/index.php
status 請求的響應狀態碼,如:200
body_bytes_sent 響應時送出的body字節數數量。即使連接中斷,這個數據也是精確的,如:40
content_length 請求頭中的Content-length字段
content_type 請求頭中的Content-Type字段
http_referer 引用地址
http_user_agent 客戶端agent信息,如:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11
args 如:_a=index&_m=show&count=10
document_uri 與$uri相同,如:/index.php
document_root 針對當前請求的根路徑設置值,如:/webserver/htdocs/dwz
hostname 如:centos53.localdomain
http_cookie 客戶端cookie信息
cookie_COOKIE cookie COOKIE變量的值
is_args 如果有$args參數,這個變量等於”?”,否則等於”",空值,如?
limit_rate 這個變量可以限制連接速率,0表示不限速
query_string 與$args相同,如:_a=index&_m=show&count=10
realpath_root 如:/webserver/htdocs/dwz
request_body 記錄POST過來的數據信息
request_body_file 客戶端請求主體信息的臨時文件名
request_method 客戶端請求的動作,通常為GET或POST,如:GET
request_uri 包含請求參數的原始URI,不包含主機名,如:”/foo/bar.php?arg=baz”。不能修改。如:/index.php_a=index&_m=show&count=10
scheme HTTP方法(如http,https),如:http
uri 如:/index.php
request_completion 如果請求結束,設置為OK. 當請求未結束或如果該請求不是請求鏈串的最后一個時,為空(Empty),如:OK
server_protocol 請求使用的協議,通常是HTTP/1.0或HTTP/1.1,如:HTTP/1.1
server_addr 服務器地址,在完成一次系統調用后可以確定這個值,如:192.168.4.129
server_name 服務器名稱,如:dwz.stamhe.com
server_port 請求到達服務器的端口號,如:80