在linux系統(tǒng)下使用nginx作為web應(yīng)用服務(wù),用來提升網(wǎng)站訪問速度的經(jīng)驗(yàn)已五年多了,今天在此對(duì)nginx的使用做一簡(jiǎn)單總結(jié)。
一、nginx服務(wù)簡(jiǎn)介
Nginx是一個(gè)高性能的HTTP和反向代理服務(wù)器,也是一個(gè) IMAP/POP3/SMTP代理服務(wù)器。Nginx 已經(jīng)因?yàn)樗姆€(wěn)定性、豐富的功能集、示例配置文件和低系統(tǒng)資源的消耗而聞名了。
使用 Nginx 前必須了解的事項(xiàng):
1)目前官方 Nginx 并不支持 Windows,您只能在包括 Linux、UNIX、BSD 系統(tǒng)下安裝和使用;
2)Nginx 本身只是一個(gè) HTTP 和反向代理服務(wù)器,它無法像 Apache 一樣通過安裝各種模塊來支持不同的頁面腳本,例如 PHP、CGI 等;
3)Nginx 支持簡(jiǎn)單的負(fù)載均衡和容錯(cuò);
4)支持作為基本 HTTP 服務(wù)器的功能,例如日志、壓縮、Byte ranges、Chunked responses、SSL、虛擬主機(jī)等等,應(yīng)有盡有。
Nginx工作原理:
Nginx由內(nèi)核和一系列模塊組成,內(nèi)核提供web服務(wù)的基本功能,如啟用網(wǎng)絡(luò)協(xié)議,創(chuàng)建運(yùn)行環(huán)境,接收和分配客戶端請(qǐng)求,處理模塊之間的交互。Nginx的各種功能和操作都由模塊來實(shí)現(xiàn)。Nginx的模塊從結(jié)構(gòu)上分為核心模塊、基礎(chǔ)模塊和第三方模塊。
1)核心模塊: HTTP模塊、EVENT模塊和MAIL模塊
2)基礎(chǔ)模塊: HTTP Access模塊、HTTP FastCGI模塊、HTTP Proxy模塊和HTTP Rewrite模塊
3)第三方模塊: HTTP Upstream Request Hash模塊、Notice模塊和HTTP Access Key模塊及用戶自己開發(fā)的模塊
這樣的設(shè)計(jì)使Nginx方便開發(fā)和擴(kuò)展,也正因此才使得Nginx功能如此強(qiáng)大。Nginx的模塊默認(rèn)編譯進(jìn)nginx中,如果需要增加或刪除模塊,需要重新編譯Nginx,這一點(diǎn)不如Apache的動(dòng)態(tài)加載模塊方便。如果有需要?jiǎng)討B(tài)加載模塊,可以使用由淘寶網(wǎng)發(fā)起的web服務(wù)器Tengine,在nginx的基礎(chǔ)上增加了很多高級(jí)特性,完全兼容Nginx,已被國(guó)內(nèi)很多網(wǎng)站采用。
Nginx處理連接過程:
nginx不會(huì)為每個(gè)連接派生進(jìn)程或線程,而是由 worker 進(jìn)程通過監(jiān)聽共享套接字接受新請(qǐng)求,并且使用高效的循環(huán)來處理數(shù)千個(gè)連接。Nginx 不使用仲裁器或分發(fā)器來分發(fā)連接,這個(gè)工作由操作系統(tǒng)內(nèi)核機(jī)制完成。監(jiān)聽套接字在啟動(dòng)時(shí)就完成初始化,worker 進(jìn)程通過這些套接字接受、讀取請(qǐng)求和輸出響應(yīng)。
Nginx的工作模式很簡(jiǎn)單,就是采用一個(gè)master進(jìn)程和多個(gè)worker工作進(jìn)程:
其中master進(jìn)程的作用也是很明確的就是負(fù)責(zé)管理worker進(jìn)程,同時(shí)監(jiān)聽連接請(qǐng)求,當(dāng)連接請(qǐng)求到來之后將連接放入worker進(jìn)程中去處理具體的業(yè)務(wù)請(qǐng)求,比如說http請(qǐng)求。 Nginx能夠處理高并發(fā)的原因在于對(duì)socket的管理方式是異步非阻塞的,使用select/poll/epoll/kqueue 來實(shí)現(xiàn)對(duì)大量socket描述符的管理,每個(gè)worker進(jìn)程有一個(gè)主線程,而沒有其他的線程這樣的好處就在于不需要進(jìn)行線程間的切換,這樣就節(jié)省了資源。所以總的來說:Nginx能夠?qū)崿F(xiàn)支持高并發(fā)的同時(shí)運(yùn)行效率還很低的關(guān)鍵在于整個(gè)系統(tǒng)內(nèi)部只有有限的幾個(gè)工作進(jìn)程和一個(gè)監(jiān)聽進(jìn)程,而每個(gè)進(jìn)程內(nèi)部只有一個(gè)主線程,這樣就不會(huì)引起很多的線程切換,從而降低了系統(tǒng)開銷,同時(shí)每個(gè)線程內(nèi)部使用異步非阻塞的方式來管理描述符這樣就可以管理大量的描述符,當(dāng)描述符多的時(shí)候也只是會(huì)占用較多的內(nèi)存而已,而不會(huì)造成占用大量cpu時(shí)間。以上說的就是Nginx的進(jìn)程模型和事件模型,事件模型中處理的情況主要有三種,分別是網(wǎng)絡(luò)事件,如HTTP請(qǐng)求等,網(wǎng)絡(luò)事件使用異步非阻塞模式就可以很好的解決;還有信號(hào),定時(shí)器,信號(hào)和定時(shí)器還不是很明白。Nginx處理進(jìn)程間爭(zhēng)奪系統(tǒng)資源的方式:也就是進(jìn)程間存在的驚群現(xiàn)象。
master:
當(dāng) nginx 在啟動(dòng)后,會(huì)有一個(gè) master 進(jìn)程和多個(gè) worker 進(jìn)程。master進(jìn)程主要用來管理worker進(jìn)程,master 要做的就是:接收來自外界的信號(hào),向各 worker 進(jìn)程發(fā)送信號(hào),監(jiān)控 worker 進(jìn)程的運(yùn)行狀態(tài),當(dāng) worker 進(jìn)程退出后(異常情況下),會(huì)自動(dòng)重新啟動(dòng)新的 worker 進(jìn)程。
主要完成如下工作:
1)讀取并驗(yàn)證配置信息;
2)創(chuàng)建、綁定及關(guān)閉套接字;
3)啟動(dòng)、終止 worker 進(jìn)程及維護(hù) worker 進(jìn)程的個(gè)數(shù);
4)無須中止服務(wù)而重新配置工作;
5)控制非中斷式程序升級(jí),啟用新的二進(jìn)制程序并在需要時(shí)回滾至老版本;
6)重新打開日志文件;
7)編譯嵌入式perl腳本
worker:
對(duì)于基本的網(wǎng)絡(luò)事件,則是放在 worker 進(jìn)程中來處理了。多個(gè) worker 進(jìn)程之間是對(duì)等的,他們同等競(jìng)爭(zhēng)來自客戶端的請(qǐng)求,各進(jìn)程互相之間是獨(dú)立的。一個(gè)請(qǐng)求,只可能在一個(gè) worker 進(jìn)程中處理,一個(gè) worker 進(jìn)程,不可能處理其它進(jìn)程的請(qǐng)求(一對(duì)一)。然而 nginx 沒有專門地仲裁或連接分布的 worker,這項(xiàng)工作是由操作系統(tǒng)內(nèi)核機(jī)制完成的。在啟動(dòng)時(shí),創(chuàng)建一組初始的監(jiān)聽套接字,HTTP 請(qǐng)求和響應(yīng)之時(shí),worker 連續(xù)接收、讀取和寫入套接字。
worker 進(jìn)程主要完成的任務(wù)包括:
1)接收、傳入并處理來自客戶端的連接;
2)提供反向代理及過濾功能;
3)nginx任何能完成的其它任務(wù)
舉例說明一個(gè)完整請(qǐng)求如何通過互相協(xié)作來實(shí)現(xiàn)的:
既然worker進(jìn)程之間是平等的,每個(gè)進(jìn)程,處理請(qǐng)求的機(jī)會(huì)也是一樣的。當(dāng)我們提供80端口的http服務(wù)時(shí),一個(gè)連接請(qǐng)求過來,每個(gè)進(jìn)程都有可能處理這個(gè)連接。那么問題來了,到底最后怎樣處理,是由什么決定的呢?首先,每個(gè) worker 進(jìn)程都是從 master 進(jìn)程 fork 過來,在 master 進(jìn)程里面,先建立好需要 listen 的 socket(listenfd)之后,然后再 fork 出多個(gè) worker 進(jìn)程。所有 worker 進(jìn)程的 listenfd 會(huì)在新連接到來時(shí)變得可讀,為保證只有一個(gè)進(jìn)程處理該連接,所有 worker 進(jìn)程會(huì)在注冊(cè) listenfd 讀事件前搶 accept_mutex,搶到互斥鎖的那個(gè)進(jìn)程注冊(cè) listenfd 讀事件,然后在讀事件里調(diào)用 accept 接受該連接。當(dāng)一個(gè) worker 進(jìn)程在 accept 這個(gè)連接之后,就開始讀取請(qǐng)求、解析請(qǐng)求、處理請(qǐng)求。產(chǎn)生數(shù)據(jù)后,再返回給客戶端,最后才斷開連接,這樣一個(gè)完整的請(qǐng)求就是這樣的了。我們可以看到:一個(gè)請(qǐng)求,完全由 worker 進(jìn)程來處理,而且只在一個(gè) worker 進(jìn)程中處理。
也許有個(gè)疑問,那就是nginx采用多worker 的方式來處理請(qǐng)求,每個(gè) worker 里面只有一個(gè)主線程,那能夠處理的并發(fā)數(shù)很有限啊,多少個(gè) worker 就能處理多少個(gè)并發(fā),何來高并發(fā)呢?
然而,這就是 nginx 的高明之處,nginx 采用了異步非阻塞的方式來處理請(qǐng)求,也就是說,nginx 是可以同時(shí)處理成千上萬個(gè)請(qǐng)求的。
異步非阻塞
異步的概念是和同步相對(duì)的,也就是不同事件之間不是同時(shí)發(fā)生的。非阻塞的概念是和阻塞對(duì)應(yīng)的,阻塞是事件按順序執(zhí)行,每一事件都要等待上一事件的完成,而非阻塞是如果事件沒有準(zhǔn)備好,這個(gè)事件可以直接返回,過一段時(shí)間再進(jìn)行處理詢問,這期間可以做其他事情。
二、nginx相對(duì)于傳統(tǒng)的apache服務(wù)的優(yōu)缺點(diǎn)
nginx相對(duì)比apache,實(shí)在有太多的優(yōu)勢(shì)??梢哉f,現(xiàn)在Nginx才是Web服務(wù)器的首選??!
1)nginx相對(duì)于apache的優(yōu)點(diǎn):
輕量級(jí),同樣起web 服務(wù),比apache 占用更少的內(nèi)存及資源;
抗并發(fā),nginx 處理請(qǐng)求是異步非阻塞的,而apache 則是阻塞型的,在高并發(fā)下nginx 能保持低資源低消耗高性能;
高度模塊化的設(shè)計(jì),編寫模塊相對(duì)簡(jiǎn)單;
社區(qū)活躍,各種高性能模塊出品迅速;
當(dāng)然apache相對(duì)于nginx也有它自身的優(yōu)點(diǎn):rewrite比nginx 的rewrite強(qiáng)大;模塊超多,基本想到的都可以找到;少bug,nginx的bug相對(duì)較多;超穩(wěn)定;apache有自帶php解析功能(apache環(huán)境部署好后,不需要再啟動(dòng)php服務(wù),apache自動(dòng)解析php文件,機(jī)器上只要有php命令即可;但是nginx不行,nginx必須結(jié)合php服務(wù)才能解析php文件,兩則服務(wù)都要啟動(dòng))
存在就是理由,一般來說,需要性能的web 服務(wù),用nginx 。
如果不需要性能只求穩(wěn)定,那就用apache。
后者的各種功能模塊實(shí)現(xiàn)得比前者,例如ssl 的模塊就比前者好,可配置項(xiàng)多。
這里要注意一點(diǎn),epoll(freebsd 上是 kqueue )網(wǎng)絡(luò)IO 模型是nginx 處理性能高的根本理由,但并不是所有的情況下都是epoll 大獲全勝的,如果本身提供靜態(tài)服務(wù)的就只有寥寥幾個(gè)文件,apache 的select 模型或許比epoll 更高性能。當(dāng)然,這只是根據(jù)網(wǎng)絡(luò)IO 模型的原理作的一個(gè)假設(shè),真正的應(yīng)用還是需要實(shí)測(cè)了再說的。
2)作為 Web 服務(wù)器:相比 Apache,Nginx 使用更少的資源,支持更多的并發(fā)連接,體現(xiàn)更高的效率,這點(diǎn)使 Nginx 尤其受到虛擬主機(jī)提供商的歡迎。在高連接并發(fā)的情況下,Nginx是Apache服務(wù)器不錯(cuò)的替代品: Nginx在美國(guó)是做虛擬主機(jī)生意的老板們經(jīng)常選擇的軟件平臺(tái)之一. 能夠支持高達(dá) 50,000 個(gè)并發(fā)連接數(shù)的響應(yīng), 感謝Nginx為我們選擇了 epoll and kqueue 作為開發(fā)模型.
Nginx作為負(fù)載均衡服務(wù)器: Nginx 既可以在內(nèi)部直接支持 Rails 和 PHP 程序?qū)ν膺M(jìn)行服務(wù), 也可以支持作為 HTTP代理 服務(wù)器對(duì)外進(jìn)行服務(wù). Nginx采用C進(jìn)行編寫, 不論是系統(tǒng)資源開銷還是CPU使用效率都比 Perlbal 要好很多.
作為郵件代理服務(wù)器: Nginx 同時(shí)也是一個(gè)非常優(yōu)秀的郵件代理服務(wù)器(最早開發(fā)這個(gè)產(chǎn)品的目的之一也是作為郵件代理服務(wù)器), Last.fm 描述了成功并且美妙的使用經(jīng)驗(yàn).
Nginx 是一個(gè)安裝非常的簡(jiǎn)單 , 配置文件非常簡(jiǎn)潔(還能夠支持perl語法), Bugs 非常少的服務(wù)器: Nginx 啟動(dòng)特別容易, 并且?guī)缀蹩梢宰龅?*24不間斷運(yùn)行,即使運(yùn)行數(shù)個(gè)月也不需要重新啟動(dòng). 你還能夠不間斷服務(wù)的情況下進(jìn)行軟件版本的升級(jí) .
3)Nginx 配置簡(jiǎn)潔,Apach復(fù)雜;Nginx靜態(tài)處理性能比Apache高3倍以上;Apache對(duì)PHP支持比較簡(jiǎn)單,Nginx需要配合其他后端用;Apache的組件比Nginx多;
4)最核心的區(qū)別在于apache是同步多進(jìn)程模型,一個(gè)連接對(duì)應(yīng)一個(gè)進(jìn)程;nginx是異步的,多個(gè)連接(萬級(jí)別)可以對(duì)應(yīng)一個(gè)進(jìn)程
5)nginx處理靜態(tài)文件好,耗費(fèi)內(nèi)存少.但apache目前也有它的優(yōu)勢(shì),有很多豐富的特性.所以還需要搭配著來.當(dāng)然如果能確定nginx就適合需求,那么使用nginx會(huì)是更經(jīng)濟(jì)的方式.
6)從個(gè)人過往的使用情況來看,nginx的負(fù)載能力比apache高很多。最新的服務(wù)器也改用nginx了。而且nginx改完配置能-t測(cè)試一下配置有沒有問題,apache重啟的時(shí)候發(fā)現(xiàn)配置出錯(cuò)了,會(huì)很崩潰,改的時(shí)候都會(huì)非常小心翼翼現(xiàn)在看有好多集群站,前端nginx抗并發(fā),后端apache集群,配合的也不錯(cuò)。
7)nginx處理動(dòng)態(tài)請(qǐng)求是雞肋,一般動(dòng)態(tài)請(qǐng)求要apache去做,nginx只適合靜態(tài)和反向。
8)從個(gè)人經(jīng)驗(yàn)來看,nginx是很不錯(cuò)的前端服務(wù)器,負(fù)載性能很好,linux服務(wù)器上運(yùn)營(yíng)nginx,用webbench模擬10000個(gè)個(gè)靜態(tài)文件請(qǐng)求毫不吃力。apache對(duì)php等語言的支持很好,此外apache有強(qiáng)大的支持網(wǎng)路,反正時(shí)間相對(duì)nginx更久,bug少,但是apache有先天不支持多核心處理負(fù)載雞肋的缺點(diǎn),所以建議使用nginx做前端,后端用apache。大型網(wǎng)站建議用nginx自代的集群功能!
9)Nginx優(yōu)于apache的主要兩點(diǎn)還體現(xiàn)在:Nginx本身就是一個(gè)反向代理服務(wù)器;Nginx支持7層負(fù)載均衡;其他的當(dāng)然,Nginx可能會(huì)比apache支持更高的并發(fā);Aapche因?yàn)槠涑墒斓募夹g(shù)和開發(fā)社區(qū),總體來說也有非常不錯(cuò)的性能,很多大公司而言還比較青睞apache。
10)你對(duì)web server的需求決定你的選擇。大部分情況下nginx都優(yōu)于apache,比如說靜態(tài)文件處理、PHP-CGI的支持、反向代理功能、前端Cache、維持連接等等。在Apache+PHP(prefork)模式下,如果PHP處理慢或者前端壓力很大的情況下,很容易出現(xiàn)Apache進(jìn)程數(shù)飆升,從而拒絕服務(wù)的現(xiàn)象。
11)對(duì)于nginx,我喜歡它配置文件寫的很簡(jiǎn)潔,正則配置讓很多事情變得簡(jiǎn)單運(yùn)行效率高,占用資源少,代理功能強(qiáng)大,很適合做前端響應(yīng)服務(wù)器
12)Apache在處理動(dòng)態(tài)有優(yōu)勢(shì),Nginx并發(fā)性比較好,CPU內(nèi)存占用低,如果rewrite頻繁,那還是Apache更好。
三、在 Linux 下安裝 Nginx
為了確保能在Nginx中使用正則表達(dá)式進(jìn)行更靈活的配置,安裝之前需要確定系統(tǒng)是否安裝有PCRE(Perl Compatible Regular s)包。
您可以到ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/下載最新的PCR 源碼包,使用下面命令下載編譯和安裝 PCRE 包:
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.7.tar.gz
# tar zxvf pcre-7.7.tar.gz
# cd pcre-7.7
# ./configure
# make
# make install
接下來安裝 Nginx,Nginx 一般有兩個(gè)版本,分別是穩(wěn)定版和開發(fā)版,您可以根據(jù)您的目的來選擇這兩個(gè)版本的其中一個(gè),下面是把 Nginx 安裝到 /opt/nginx 目錄下的詳細(xì)步驟:
# wget http://sysoev.ru/nginx/nginx-0.6.31.tar.gz
# tar zxvf nginx-0.6.31.tar.gz
# cd nginx-0.6.31
# ./configure --with-http_stub_status_module –prefix=/opt/nginx
# make
# make install
其中參數(shù) --with-http_stub_status_module 是為了啟用 nginx 的 NginxStatus 功能,用來監(jiān)控 Nginx 的當(dāng)前狀態(tài)。
安裝成功后/opt/nginx 目錄下有四個(gè)子目錄分別是:conf、html、logs、sbin 。
其中Nginx的配置文件存放于conf/nginx.conf,Nginx只有一個(gè)程序文件位于sbin目錄下的nginx文件。
確保系統(tǒng)的80端口沒被其他程序占用,運(yùn)行sbin/nginx命令來啟動(dòng)Nginx,打開瀏覽器訪問此機(jī)器的 IP,如果瀏覽器出現(xiàn) Welcome to nginx! 則表示 Nginx 已經(jīng)安裝并運(yùn)行成功。
常用的 Nginx 參數(shù)和控制
程序運(yùn)行參數(shù)
Nginx 安裝后只有一個(gè)程序文件,本身并不提供各種管理程序,它是使用參數(shù)和系統(tǒng)信號(hào)機(jī)制對(duì) Nginx 進(jìn)程本身進(jìn)行控制的。 Nginx 的參數(shù)包括有如下幾個(gè):
-c <path_to_config>:使用指定的配置文件而不是 conf 目錄下的 nginx.conf 。
-t:測(cè)試配置文件是否正確,在運(yùn)行時(shí)需要重新加載配置的時(shí)候,此命令非常重要,用來檢測(cè)所修改的配置文件是否有語法錯(cuò)誤。
-v:顯示 nginx 版本號(hào)。
-V:顯示 nginx 的版本號(hào)以及編譯環(huán)境信息以及編譯時(shí)的參數(shù)。
例如我們要測(cè)試某個(gè)配置文件是否書寫正確,我們可以使用以下命令
sbin/nginx – t – c conf/nginx2.conf
通過信號(hào)對(duì) Nginx 進(jìn)行控制
Nginx 支持下表中的信號(hào):
有兩種方式來通過這些信號(hào)去控制Nginx:
第一是通過logs目錄下的nginx.pid查看當(dāng)前運(yùn)行的Nginx的進(jìn)程ID,通過 kill – XXX <pid> 來控制 Nginx,其中 XXX 就是上表中列出的信號(hào)名。
如果系統(tǒng)中只有一個(gè)Nginx進(jìn)程,那也可以通過 killall 命令來完成,例如運(yùn)行 killall – s HUP nginx 來讓 Nginx 重新加載配置。
配置 Nginx
先來看一個(gè)實(shí)際的配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | user nobody; # 工作進(jìn)程的屬主 worker_processes 4; # 工作進(jìn)程數(shù),一般與 CPU 核數(shù)等同 #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; # 每個(gè)工作進(jìn)程允許最大的同時(shí)連接數(shù) } 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; # 集群中的所有后臺(tái)服務(wù)器的配置信息 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 狀態(tài)監(jiān)控配置 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 監(jiān)控
上面是一個(gè)實(shí)際網(wǎng)站的配置實(shí)例,其中#號(hào)后面的文字為配置說明。
上述配置中,首先我們定義了一個(gè) location ~ ^/NginxStatus/,這樣通過 http://localhost/NginxStatus/ 就可以監(jiān)控到 Nginx 的運(yùn)行信息,顯示的內(nèi)容如下:
Active connections: 70
server accepts handled requests
14553819 14553819 19239266
Reading: 0 Writing: 3 Waiting: 67
NginxStatus 顯示的內(nèi)容意思如下:
active connections – 當(dāng)前 Nginx 正處理的活動(dòng)連接數(shù)。
server accepts handled requests -- 總共處理了 14553819 個(gè)連接 , 成功創(chuàng)建 14553819 次握手 ( 證明中間沒有失敗的 ), 總共處理了 19239266 個(gè)請(qǐng)求 ( 平均每次握手處理了 1.3 個(gè)數(shù)據(jù)請(qǐng)求 )。
reading -- nginx 讀取到客戶端的 Header 信息數(shù)。
writing -- nginx 返回給客戶端的 Header 信息數(shù)。
waiting -- 開啟 keep-alive 的情況下,這個(gè)值等于 active - (reading + writing),意思就是 Nginx 已經(jīng)處理完正在等候下一次請(qǐng)求指令的駐留連接。
靜態(tài)文件處理
通過正則表達(dá)式,我們可讓 Nginx 識(shí)別出各種靜態(tài)文件,例如 images 路徑下的所有請(qǐng)求可以寫為:
location ~ ^/images/ {
root /opt/webapp/images;
}
而下面的配置則定義了幾種文件類型的請(qǐng)求處理方式。
location ~ \.(htm|html|gif|jpg|jpeg|png|bmp|ico|css|js|txt)$ {
root /opt/webapp;
expires 24h;
}
對(duì)于例如圖片、靜態(tài) HTML 文件、js 腳本文件和 css 樣式文件等,我們希望 Nginx 直接處理并返回給瀏覽器,這樣可以大大的加快網(wǎng)頁瀏覽時(shí)的速度。因此對(duì)于這類文件我們需要通過 root 指令來指定文件的存放路徑,同時(shí)因?yàn)檫@類文件并不常修改,通過 expires 指令來控制其在瀏覽器的緩存,以減少不必要的請(qǐng)求。 expires 指令可以控制 HTTP 應(yīng)答中的“ Expires ”和“ Cache-Control ”的頭標(biāo)(起到控制頁面緩存的作用)。您可以使用例如以下的格式來書寫 Expires:
expires 1 January, 1970, 00:00:01 GMT;
expires 60s;
expires 30m;
expires 24h;
expires 1d;
expires max;
expires off;
動(dòng)態(tài)頁面請(qǐng)求處理
Nginx 本身并不支持現(xiàn)在流行的 JSP、ASP、PHP、PERL 等動(dòng)態(tài)頁面,但是它可以通過反向代理將請(qǐng)求發(fā)送到后端的服務(wù)器,例如 Tomcat、Apache、IIS 等來完成動(dòng)態(tài)頁面的請(qǐng)求處理。前面的配置示例中,我們首先定義了由 Nginx 直接處理的一些靜態(tài)文件請(qǐng)求后,其他所有的請(qǐng)求通過 proxy_pass 指令傳送給后端的服務(wù)器(在上述例子中是 Tomcat)。最簡(jiǎn)單的 proxy_pass 用法如下:
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
}
這里我們沒有使用到集群,而是將請(qǐng)求直接送到運(yùn)行在 8080 端口的 Tomcat 服務(wù)上來完成類似 JSP 和 Servlet 的請(qǐng)求處理。
當(dāng)頁面的訪問量非常大的時(shí)候,往往需要多個(gè)應(yīng)用服務(wù)器來共同承擔(dān)動(dòng)態(tài)頁面的執(zhí)行操作,這時(shí)我們就需要使用集群的架構(gòu)。 Nginx 通過 upstream 指令來定義一個(gè)服務(wù)器的集群,最前面那個(gè)完整的例子中我們定義了一個(gè)名為 tomcats 的集群,這個(gè)集群中包括了三臺(tái)服務(wù)器共 6 個(gè) Tomcat 服務(wù)。而 proxy_pass 指令的寫法變成了:
location / {
proxy_pass http://tomcats;
proxy_set_header X-Real-IP $remote_addr;
}
在 Nginx 的集群配置中,Nginx 使用最簡(jiǎn)單的平均分配規(guī)則給集群中的每個(gè)節(jié)點(diǎn)分配請(qǐng)求。一旦某個(gè)節(jié)點(diǎn)失效時(shí),或者重新起效時(shí),Nginx 都會(huì)非常及時(shí)的處理狀態(tài)的變化,以保證不會(huì)影響到用戶的訪問。
Nginx的location語法規(guī)則:location [=|~|~*|^~] /uri/ { … }
= 開頭表示精確匹配
^~ 開頭表示uri以某個(gè)常規(guī)字符串開頭,理解為匹配 url路徑即可。nginx不對(duì)url做編碼,因此請(qǐng)求為/static/20%/aa,可以被規(guī)則^~ /static/ /aa匹配到(注意是空格)。
~ 開頭表示區(qū)分大小寫的正則匹配
~* 開頭表示不區(qū)分大小寫的正則匹配
!~和!~* 分別為區(qū)分大小寫不匹配及不區(qū)分大小寫不匹配 的正則
/ 通用匹配,任何請(qǐng)求都會(huì)匹配到。
多個(gè)location配置的情況下匹配順序?yàn)椋▍⒖假Y料而來,還未實(shí)際驗(yàn)證,試試就知道了,不必拘泥,僅供參考):
首先匹配 =,其次匹配^~, 其次是按文件中順序的正則匹配,最后是交給 / 通用匹配。當(dāng)有匹配成功時(shí)候,停止匹配,按當(dāng)前匹配規(guī)則處理請(qǐng)求。
示例說明:
有如下匹配規(guī)則:
location = / {
#規(guī)則A
}
location = /login {
#規(guī)則B
}
location ^~ /static/ {
#規(guī)則C
}
location ~ \.(gif|jpg|png|js|css)$ {
#規(guī)則D
}
location ~* \.png$ {
#規(guī)則E
}
location !~ \.xhtml$ {
#規(guī)則F
}
location !~* \.xhtml$ {
#規(guī)則G
}
location / {
#規(guī)則H
}
產(chǎn)生的效果如下:
訪問根目錄/, 比如http://localhost/ 將匹配規(guī)則A
訪問http://localhost/login 將匹配規(guī)則B,http://localhost/register 則匹配規(guī)則H
訪問http://localhost/static/a.html 將匹配規(guī)則C
訪問http://localhost/a.gif, http://localhost/b.jpg 將匹配規(guī)則D和規(guī)則E,但是規(guī)則D順序優(yōu)先,規(guī)則E不起作用, 而 http://localhost/static/c.png 則優(yōu)先匹配到 規(guī)則C
訪問http://localhost/a.PNG 則匹配規(guī)則E, 而不會(huì)匹配規(guī)則D,因?yàn)橐?guī)則E不區(qū)分大小寫。
訪問http://localhost/a.xhtml 不會(huì)匹配規(guī)則F和規(guī)則G,http://localhost/a.XHTML不會(huì)匹配規(guī)則G,因?yàn)椴粎^(qū)分大小寫。規(guī)則F,規(guī)則G屬于排除法,符合匹配規(guī)則但是不會(huì)匹配到,所以想想看實(shí)際應(yīng)用中哪里會(huì)用到。
訪問http://localhost/category/id/1111 則最終匹配到規(guī)則H,因?yàn)橐陨弦?guī)則都不匹配,這個(gè)時(shí)候應(yīng)該是nginx轉(zhuǎn)發(fā)請(qǐng)求給后端應(yīng)用服務(wù)器,比如FastCGI(php),tomcat(jsp),nginx作為方向代理服務(wù)器存在。
所以實(shí)際使用中,至少有三個(gè)匹配規(guī)則定義,如下:
直接匹配網(wǎng)站根,通過域名訪問網(wǎng)站首頁比較頻繁,使用這個(gè)會(huì)加速處理,官網(wǎng)如是說。
這里是直接轉(zhuǎn)發(fā)給后端應(yīng)用服務(wù)器了,也可以是一個(gè)靜態(tài)首頁
第一個(gè)必選規(guī)則
location = / {
proxy_pass http://tomcat:8080/index
}
第二個(gè)必選規(guī)則是處理靜態(tài)文件請(qǐng)求,這是nginx作為http服務(wù)器的強(qiáng)項(xiàng)
有兩種配置模式,目錄匹配或后綴匹配,任選其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三個(gè)規(guī)則就是通用規(guī)則,用來轉(zhuǎn)發(fā)動(dòng)態(tài)請(qǐng)求到后端應(yīng)用服務(wù)器
非靜態(tài)文件請(qǐng)求就默認(rèn)是動(dòng)態(tài)請(qǐng)求,自己根據(jù)實(shí)際把握
畢竟目前的一些框架的流行,帶.php,.jsp后綴的情況很少了
location / {
proxy_pass http://tomcat:8080/
}
盡管Nginx整個(gè)程序包只有500多K,但麻雀雖小、五臟俱全。 Nginx官方提供的各種功能模塊應(yīng)有盡有,結(jié)合這些模塊可以完整各種各樣的配置要求,例如:壓縮、防盜鏈、集群、FastCGI、流媒體服務(wù)器、Memcached 支持、URL 重寫等等,更關(guān)鍵的是Nginx擁有Apache和其他HTTP服務(wù)器無法比擬的高性能。甚至可以在不改變?cè)芯W(wǎng)站的架構(gòu)上,通過在前端引入Nginx做負(fù)載均衡來提升網(wǎng)站的訪問速度。
-------------------------------------------------------下面對(duì)Nginx的一些特殊設(shè)置做一說明-------------------------------------------------------
nginx的全局變量
--------------------------------------------------------------------------------
remote_addr 客戶端ip,如:192.168.4.2
binary_remote_addr 客戶端ip(二進(jìn)制)
remote_port 客戶端port,如:50472
remote_user 已經(jīng)經(jīng)過Auth Basic Module驗(yàn)證的用戶名
host 請(qǐng)求主機(jī)頭字段,否則為服務(wù)器名稱,如:dwz.stamhe.com
request 用戶請(qǐng)求信息,如:GET /?_a=index&_m=show&count=10 HTTP/1.1
request_filename 當(dāng)前請(qǐng)求的文件的路徑名,由root或alias和URI request組合而成,如:/webserver/htdocs/dwz/index.php
status 請(qǐng)求的響應(yīng)狀態(tài)碼,如:200
body_bytes_sent 響應(yīng)時(shí)送出的body字節(jié)數(shù)數(shù)量。即使連接中斷,這個(gè)數(shù)據(jù)也是精確的,如:40
content_length 請(qǐng)求頭中的Content-length字段
content_type 請(qǐng)求頭中的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 針對(duì)當(dāng)前請(qǐng)求的根路徑設(shè)置值,如:/webserver/htdocs/dwz
hostname 如:centos53.localdomain
http_cookie 客戶端cookie信息
cookie_COOKIE cookie COOKIE變量的值
is_args 如果有$args參數(shù),這個(gè)變量等于”?”,否則等于”",空值,如?
limit_rate 這個(gè)變量可以限制連接速率,0表示不限速
query_string 與$args相同,如:_a=index&_m=show&count=10
realpath_root 如:/webserver/htdocs/dwz
request_body 記錄POST過來的數(shù)據(jù)信息
request_body_file 客戶端請(qǐng)求主體信息的臨時(shí)文件名
request_method 客戶端請(qǐng)求的動(dòng)作,通常為GET或POST,如:GET
request_uri 包含請(qǐng)求參數(shù)的原始URI,不包含主機(jī)名,如:”/foo/bar.php?arg=baz”。不能修改。如:/index.php?_a=index&_m=show&count=10
scheme HTTP方法(如http,https),如:http
uri 如:/index.php
request_completion 如果請(qǐng)求結(jié)束,設(shè)置為OK. 當(dāng)請(qǐng)求未結(jié)束或如果該請(qǐng)求不是請(qǐng)求鏈串的最后一個(gè)時(shí),為空(Empty),如:OK
server_protocol 請(qǐng)求使用的協(xié)議,通常是HTTP/1.0或HTTP/1.1,如:HTTP/1.1
server_addr 服務(wù)器地址,在完成一次系統(tǒng)調(diào)用后可以確定這個(gè)值,如:192.168.4.129
server_name 服務(wù)器名稱,如:dwz.stamhe.com
server_port 請(qǐng)求到達(dá)服務(wù)器的端口號(hào),如:80
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 比如訪問https: //www .wangshibo.com /HouseGroup/index .html,跳轉(zhuǎn)到https: //www .wangshibo.com /index .php?r=houseGroup /index rewrite ^/(.*) /index .html https: //www .wangshibo.com /index .php?r=$1 /index ; if ($request_uri ~* "/(jkhwpc|jkhw|jkhwadmin).php" ) { rewrite ^/(.*)$ http: //www .jikehaiwai.com/$1 last; } if ($request_uri ~* "/(qjspc|qjsmob|qjsadmin).php" ) { rewrite ^/(.*)$ http: //www .qianjins.com/$1 last; } -----------可以參考下面nginx的rewrite偽靜態(tài)設(shè)置--------- rewrite ^(.*) /equip (d+).html$ $1 /index .php?m=content&c=index&a=lists&catid=$2 last; # nginx rewrite rule rewrite ^(.*) /archiver/ ((fid|tid)-[w-]+.html)$ $1 /archiver/index .php?$2 last; rewrite ^(.*) /forum- ([0-9]+)-([0-9]+).html$ $1 /forumdisplay .php?fid=$2&page=$3 last; rewrite ^(.*) /thread- ([0-9]+)-([0-9]+)-([0-9]+).html$ $1 /viewthread .php?tid=$2&extra=page%3D$4&page=$3 last; rewrite ^(.*) /profile- (username|uid)-(.+).html$ $1 /viewpro .php?$2=$3 last; rewrite ^(.*) /space- (username|uid)-(.+).html$ $1 /space .php?$2=$3 last; rewrite ^(.*) /tag- (.+).html$ $1 /tag .php?name=$2 last; rewrite ^/(.*)\.(asp|aspx|asa|asax|dll|jsp|cgi|fcgi|pl)(.*)$ /404 .php last; rewrite ^/(.*)/(admin|cache|editor| file |include|lang|module|skin|template)/(.*)\.php(.*)$ /404 .php last; rewrite ^/(.*)-htm-(.*)$ /$1.php?$2 last; rewrite ^/(.*) /show- ([0-9]+)([\-])?([0-9]+)?\.html$ /$1 /show .php?itemid=$2&page=$4 last; rewrite ^/(.*) /list- ([0-9]+)([\-])?([0-9]+)?\.html$ /$1 /list .php?catid=$2&page=$4 last; rewrite ^/(.*) /show/ ([0-9]+)/([0-9]+)?([/])?$ /$1 /show .php?itemid=$2&page=$3 last; rewrite ^/(.*) /list/ ([0-9]+)/([0-9]+)?([/])?$ /$1 /list .php?catid=$2&page=$3 last; rewrite ^/(.*)/([A-za-z0-9_\-]+)-c([0-9]+)-([0-9]+)\.html$ /$1 /list .php?catid=$3&page=$4 last; rewrite ^/(.*)/([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /$1 /index .php?moduleid=$2&catid=$3&itemid=$4&page=$5 last; rewrite ^(.*)/([a-z]+)/(.*)\.shtml$ $1/$2 /index .php?rewrite=$3 last; rewrite ^/(com)/([a-z0-9_\-]+)/([a-z]+)/(.*)\.html$ /index .php?homepage=$2& file =$3&rewrite=$4 last; rewrite ^/(com)/([a-z0-9_\-]+)/([a-z]+)([/])?$ /index .php?homepage=$2& file =$3 last; rewrite ^/(com)/([a-z0-9_\-]+)([/])?$ /index .php?homepage=$2 last; |
--------------------------------------------------------------------------------
1.rewrite跳轉(zhuǎn)規(guī)則,有以下四種flag標(biāo)記:
last 基本上都用這個(gè)Flag,表示rewrite。
break 中止Rewirte,不在繼續(xù)匹配。就是說本條規(guī)則匹配完成后,終止匹配,不再匹配后面的規(guī)則。
redirect 返回臨時(shí)重定向的HTTP狀態(tài)302;瀏覽器地址會(huì)顯示跳轉(zhuǎn)后的URL地址。
permanent 返回永久重定向的HTTP狀態(tài)301;瀏覽器地址會(huì)顯示跳轉(zhuǎn)后的URL地址。
1)下面是可以用來判斷的表達(dá)式:
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執(zhí)行
先來看幾個(gè)小例子說明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 例如下面這段設(shè)定nginx將某個(gè)目錄下面的文件重定向到另一個(gè)目錄,$2對(duì)應(yīng)第二個(gè)括號(hào)(.*)中對(duì)應(yīng)的字符串: location /download/ { rewrite ^( /download/ .*) /m/ (.*)\..*$ $1 /nginx-rewrite/ $2.gz break ; } ----------------------------------------------------------------------------------- 例如當(dāng)用戶輸入 www.a.com.cn 自動(dòng)跳轉(zhuǎn)到www.a.com 這個(gè)域名: rewrite ^/(.*)$ http: //www .a.com/$1 permanent; ----------------------------------------------------------------------------------- 例如下面設(shè)定nginx在用戶使用ie的使用重定向到 /nginx-ie 目錄下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/ $1 break ; } ----------------------------------------------------------------------------------- 例如當(dāng)用戶訪問testxqsjapi.xqshijie.com域名時(shí)跳轉(zhuǎn)到本機(jī)的9501端口 upstream lb-9501 { server 127.0.0.1:9501; } server { listen 80; server_name testxqsjapi.xqshijie.com; root /var/www/vhosts/testxqsjapi .xqshijie.com/; location / { proxy_pass http: //lb-9501 ; } } ---------------------------------------------------------------------------------- 例如下面一例:nginx rewrite 實(shí)現(xiàn)二級(jí)域名跳轉(zhuǎn) 當(dāng)訪問http: //abc .wangshibo.com跳轉(zhuǎn)到http: //www .wangshibo.com /wangshibo/abc/ 方法一:這種方法瀏覽器地址會(huì)變www.wangshibo.com /wangshibo/abc server { listen 80; server_name www.wangshibo.com; location / { root /data/wangshibo ; index index.html; } } server { listen 80; server_name *.wangshibo.com; if ( $http_host ~* "^(.*)\.wangshibo\.com$" ) { set $domain $1; rewrite ^(.*) http: //www .wangshibo.com /wangshibo/ $domain/ break ; } } 方法二:當(dāng)訪問http: //abc .wangshibo.com跳轉(zhuǎn)到http: //www .wangshibo.com /wangshibo/abc/ server { listen 80; server_name *.wangshibo.com; root /usr/local/www ; #這是里可以加多個(gè)目錄,如果不加目錄,會(huì)無法訪問到abc.wangshibo.com/目錄下的文件,如圖片目錄/images location ~ ^/(wangshibo|images|styles)/ { proxy_redirect off; proxy_set_header Host www.wangshibo.com; proxy_pass http: //192 .168.1.2:8080; } location / { set $domain default; if ( $http_host ~* "^(.*)\.wangshibo\.com$" ) { set $domain $1; } rewrite ^/(.*) /wangshibo/ $domain/$1 last; } access_log off; } |
再接著看下面的實(shí)例說明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #直接匹配網(wǎng)站根,通過域名訪問網(wǎng)站首頁比較頻繁,使用這個(gè)會(huì)加速處理,官網(wǎng)如是說。 #這里是直接轉(zhuǎn)發(fā)給后端應(yīng)用服務(wù)器了,也可以是一個(gè)靜態(tài)首頁 # 第一個(gè)必選規(guī)則 location = / { proxy_pass http: //tomcat :8080 /index } # 第二個(gè)必選規(guī)則是處理靜態(tài)文件請(qǐng)求,這是nginx作為http服務(wù)器的強(qiáng)項(xiàng) # 有兩種配置模式,目錄匹配或后綴匹配,任選其一或搭配使用 location ^~ /static/ { root /webroot/static/ ; } location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/ ; } #第三個(gè)規(guī)則就是通用規(guī)則,用來轉(zhuǎn)發(fā)動(dòng)態(tài)請(qǐng)求到后端應(yīng)用服務(wù)器 #非靜態(tài)文件請(qǐng)求就默認(rèn)是動(dòng)態(tài)請(qǐng)求,自己根據(jù)實(shí)際把握 #畢竟目前的一些框架的流行,帶.php,.jsp后綴的情況很少了 location / { proxy_pass http: //tomcat :8080/ } |
2)實(shí)例說明
1)訪問A站跳轉(zhuǎn)(重定向)到B站
server {
listen 80;
server_name www.wangshibo.com ;
rewrite ^(.*) http://www.huanqiu.com$1 permanent;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 訪問wangshibo.com跳轉(zhuǎn)到www.wangshibo.com server { listen 80; server_name www.wangshibo.com wangshibo.com; index index.jsp index.html index.php index.htm; root /var/www/html ; access_log /usr/local/nginx/logs/image .log; if ($host = "wangshibo.com" ) { rewrite ^/(.*)$ http: //www .wangshibo.com permanent; } } |
2)多域名綁定一個(gè)目錄,并且全部301跳轉(zhuǎn)到其中一個(gè)域名(注意:多域名都要解析到本機(jī)ip上)
server {
listen 80;
server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;
if ($host != 'www.wangshibo.com') {
rewrite ^/(.*)$ http://www.wangshibo.com/$1 permanent;
}
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
上面說明訪問http://web01.wangshibo.com、http://hehe.wangshibo.com、http://wangshibo.com的時(shí)候都會(huì)自動(dòng)跳轉(zhuǎn)到
http://www.wangshibo.com,并且瀏覽器地址會(huì)顯示跳轉(zhuǎn)后的URL地址。
如果是上面多域名訪問后都重定向跳轉(zhuǎn)到http://hehe.wangshibo.com,則配置修改如下:
server {
listen 80;
server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;
if ($host != 'hehe.wangshibo.com') {
rewrite ^/(.*)$ http://hehe.wangshibo.com/$1 permanent;
}
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
如下配置:多域名中的某個(gè)域名訪問時(shí)發(fā)生跳轉(zhuǎn),其他域名訪問時(shí)不跳轉(zhuǎn)
server {
listen 80;
server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com;
if ($host = 'hehe.wangshibo.com') {
rewrite ^/(.*)$ http://www.huanqiu.com/$1 permanent;
}
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
3)將多級(jí)目錄下的文件轉(zhuǎn)成一個(gè)文件,增強(qiáng)seo效果
比如將/wang-123-456-789.html指向wang/123/456/wangshow_789.html
[root@test-huanqiu ~]# cat /usr/local/nginx/conf/vhosts/test.conf
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/wang-([0-9]+)-([0-9]+)-([0-9]+)\.html$ http://www.wangshibo.com/wang/$1/$2/wangshow_$3.html last;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
這樣訪問http://www.wangshibo.com/wang-123-456-789.html就會(huì)跳轉(zhuǎn)到http://www.wangshibo.com/wang/123/456/wangshow_789.html
4)訪問的目標(biāo)文件和目錄資源不存在的時(shí)候重定向跳轉(zhuǎn)
如下配置,當(dāng)訪問http://www.wangshibo.com/后面的訪問資源(文件或目錄)不存在時(shí),統(tǒng)統(tǒng)跳轉(zhuǎn)到http://www.wangshibo.com/sorry.html頁面
server {
listen 80;
server_name www.wangshibo.com;
if (!-e $request_filename) {
rewrite ^/ http://www.wangshibo.com/sorry.html ;
}
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
5)將站點(diǎn)根目錄下某個(gè)目錄指向二級(jí)目錄
例如將/huanqiupc/指向/ops/huanqiu/,配置如下:
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/([0-9a-z]+)pc/(.*)$ http://www.wangshibo.com/ops/$1/$2 last;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
這樣,訪問http://www.wangshibo.com/huanqiupc的時(shí)候就會(huì)跳轉(zhuǎn)到http://www.wangshibo.com/ops/huanqiu/
注意:上面的配置中的last修改為permanent或redirect都可以
以上的配置也適用于:(前提是這些目錄要真是存在于站點(diǎn)目錄/var/www/html/中,并且權(quán)限要正確)
將/wangshibopc/指向/ops/wangshibo/
將/guohuihuipc/指向/ops/guohuihui/
將/hahapc/指向/ops/haha/
......
6)其他的rewrite跳轉(zhuǎn)規(guī)則的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | server { listen 80; server_name www.wangshibo.com; root /var/www/html ; index index.html index.htm; rewrite ^ /site/resource/ (.*)$ https: //www .wangshibo.com /resource/ $1 last; rewrite ^ /active/Ymf .html$ https: //www .wangshibo.com /project/detail .html?project_id=1 last; rewrite ^ /active/Ysyg .html$ https: //www .wangshibo.com /project/detail .html?project_id=7 last; if ($host ~* "^wangshibo.com$" ) { rewrite ^/(.*)$ https: //www .wangshibo.com/ permanent; } location / { rewrite /abc http: //www .huanqiu.com break ; #本機(jī)站點(diǎn)目錄下并不需要真實(shí)存在abc這個(gè)目錄,對(duì)虛擬目錄的訪問都重寫到http://www.huanqiu.com } #即訪問http://www.wangshibo.com/abc,跳轉(zhuǎn)到http://www.huanqiu.com location /text { rewrite / http: //china .huanqiu.com break ; #本機(jī)站點(diǎn)目錄下需要真實(shí)存在text目錄,對(duì)其的訪問都重寫到http://china.huanqiu.com } #即訪問http://www.wangshibo.com/text,跳轉(zhuǎn)到http://china.huanqiu.com } |
下面一例:訪問http://www.wangshibo.com/g/4HG45SkZ 實(shí)際訪問地址跳轉(zhuǎn)為 http://110.10.88.99:8081/qun/share/view?code=4HG45SkZ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | upstream g_server { keepalive 64; server 110.10.88.99:8081 max_fails=2 fail_timeout=5 weight=100; } server { listen 80; server_name www.wangshibo.com; rewrite ^/bcloud.(swf|html|js)(.*)$ http: //hehe.wangshibo.com/bcloud.$1$2 last; root /home/web/www; location ~ \.apk$ { max_ranges 0; } location ^~ /g { proxy_redirect off; proxy_set_header Host $host; # proxy_set_header Host $host:$remote_port; # proxy_set_header REMOTE_PORT $remote_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 1G; client_body_buffer_size 256k; proxy_connect_timeout 30; proxy_send_timeout 30; proxy_read_timeout 600; proxy_buffer_size 16k; proxy_buffers 4 32k; proxy_temp_file_write_size 64k; proxy_pass http: //g_server; #rewrite "/g/(.*$)" www.wangshibo.com/qun/share/view?code=$1 break; rewrite "/g/(.*$)" /qun/share/view?code=$1 break ; } } |
另外注意:
$1表示第一個(gè)變量,即前面rewrite后第一個(gè)()內(nèi)設(shè)置的變量
$2表示第二個(gè)變量,即前面rewrite后第二個(gè)()內(nèi)設(shè)置的變量
再看一例:
訪問http://www.wangshibo.com/thumb/transcode 實(shí)際訪問地址為 http://120.170.190.99:28080/transcode/thumb/transcode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | upstream thumb { keepalive 64; server 120.170.190.99:28080 max_fails=2 fail_timeout=5 weight=100; } server { listen 80; server_name www.wangshibo.com ; root /home/web/www; location ^~ /thumb { proxy_pass http: //thumb; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for; client_max_body_size 1G; client_body_buffer_size 256k; proxy_connect_timeout 30; proxy_send_timeout 30; proxy_read_timeout 60; proxy_buffer_size 16k; proxy_buffers 4 32k; proxy_temp_file_write_size 64k; rewrite "^/(.*)$" /transcode/$1 break ; } } |
----------------------------再看一個(gè)訪問nginx跳轉(zhuǎn)后的url不變的例子--------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 需要特別注意的是: proxy_pass 反向代理,可以實(shí)現(xiàn)只改變跳轉(zhuǎn)后的內(nèi)容,而跳轉(zhuǎn)后的原url保持不變! rewrite 重寫跳轉(zhuǎn)后會(huì)進(jìn)行重定向,很難實(shí)現(xiàn)跳轉(zhuǎn)后的原url不變的需求。 看看之前踩過的坑; 要求訪問http: //wx2 .xqshijie.com /apiwx2/xqsj .php?r=houseGroup%2FgetToken,內(nèi)容跳轉(zhuǎn)到http: //m .xqshijie.com /xqsj .php?r=houseGroup%2FgetToken,但是跳轉(zhuǎn)后的url保持不變! 這是根據(jù)path路徑進(jìn)行反向代理的配置,即要求訪問http: //wx2 .xqshijie.com /apiwx2/ $1 跳轉(zhuǎn)到http: //m .xqshijie.com/$1,跳轉(zhuǎn)后的url不變! 配置如下: [root@fangfull_web1 vhosts] # cat wx2.xqshijie.com.conf server { listen 80; server_name wx2.xqshijie.com; root /Data/app/xqsj_wx2/dist ; index index.html; #if ($http_x_forwarded_for !~ ^(124.65.197.154|103.10.86.28|103.10.86.8)) { # rewrite ^.*$ /maintence.php last; #} location /apiwx2/ { proxy_pass https: //m .xqshijie.com/; } access_log /var/log/betawx2 .log main; location / { try_files $uri $uri/ @router; index index.html; } #rewrite ^(.+)$ /index.html last; location @router { rewrite ^.*$ /index .html last; } } 根據(jù)上面配置后,就可以實(shí)現(xiàn)訪問http: //wx2 .xqshijie.com /apiwx2/xqsj .php?r=houseGroup%2FgetToken,實(shí)際顯示的是https: //m .xqshijie.com /xqsj .php?r=houseGroup%2FgetToken的內(nèi)容,但是跳轉(zhuǎn)后的原來的url不變! 如果采用rewrite重寫規(guī)則,即將: location /apiwx2/ { proxy_pass https: //m .xqshijie.com/; } 改為 location /apiwx2/ { rewrite ^ /apiwx2 (.*)$ https: //m .xqshijie.com.$1 last; } 那么,訪問http: //wx2 .xqshijie.com /apiwx2/xqsj .php?r=houseGroup%2FgetToken,實(shí)際顯示的是https: //m .xqshijie.com /xqsj .php?r=houseGroup%2FgetToken的內(nèi)容,但是跳轉(zhuǎn)后的url已經(jīng)變了! 上面碰到過的坑: 由于訪問http: //m .xqshijie.com就會(huì)自動(dòng)跳轉(zhuǎn)到https: //m .xqshijie.com,所以如果將上面的配置改為(即將https: //m .xqshijie.com改為http: //m .xqshijie.com): location /apiwx2/ { proxy_pass http: //m .xqshijie.com/; } 這樣,訪問http: //wx2 .xqshijie.com /apiwx2/xqsj .php?r=houseGroup%2FgetToken,實(shí)際顯示的是https: //m .xqshijie.com /xqsj .php?r=houseGroup%2FgetToken的內(nèi)容,但是跳轉(zhuǎn)后的原來的url已經(jīng)變了! 原因是因?yàn)檫@里經(jīng)過了兩次跳轉(zhuǎn),即rewrite->http->https,所以跳轉(zhuǎn)后的url變了。 解決辦法:就是直接rewrite跳轉(zhuǎn)到https,即proxy_pass https: //m .xqshijie.com/; |
----------------------------下面的跳轉(zhuǎn)規(guī)則表示---------------------------------------
訪問http://www.wangshibo.com/wangshibo/ops就會(huì)跳轉(zhuǎn)到http://www.wangshibo.com/ops/wangshibo
訪問http://www.wangshibo.com/wangshibo/beijing就會(huì)跳轉(zhuǎn)到http://www.wangshibo.com/beijing/wangshibo
......
即由"wangshibo/變量"-->"變量/wangshibo"
1 2 3 4 5 6 7 8 | server { listen 80; server_name www.wangshibo.com; rewrite ^/wangshibo/(.*)$ http: //www.wangshibo.com/$1/wangshibo last; root / var /www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } |
訪問http://www.wangshibo.com/ops/web 跳轉(zhuǎn)到 http://www.wangshibo.com/web/ops/web/
1 2 3 4 5 6 7 8 | server { listen 80; server_name www.wangshibo.com; rewrite ^ /ops/ (.*)$ http: //www .wangshibo.com/$1 /ops/ $1 break ; root /var/www/html ; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image .log; } |
訪問http://www.wangshibo.com/wang/123 實(shí)際訪問地址跳轉(zhuǎn)為 http://www.hehe.com/qun/share/view?code=123
1 2 3 4 5 6 7 8 | server { listen 80; server_name www.wangshibo.com; rewrite ^ /wang/ (.*)$ http: //www .hehe.com /qun/share/view ?code=$1 last; root /var/www/html ; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image .log; } |
其他配置實(shí)例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 如果nginx在用戶使用IE瀏覽器訪問情況下,則重定向到 /nginx-ie 目錄下 配置如下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/ $1 break ; } 多目錄轉(zhuǎn)成參數(shù) abc.domian.com /sort/2 => abc.domian.com /index .php?act= sort &name=abc& id =2 配置如下: if ($host ~* (.*)\.domain\.com) { set $sub_name $1; rewrite ^ /sort \/(\d+)\/?$ /index .php?act= sort &cid=$sub_name& id =$1 last; } 目錄自動(dòng)加 "/" ,前提是訪問目錄存在 配置如下: if (-d $request_filename){ rewrite ^/(.*)([^/])$ http: // $host/$1$2/ permanent; } 三級(jí)域名跳轉(zhuǎn) 配置如下: if ($http_host ~* “^(.*)\.i\.beijing\.com$”) { rewrite ^(.*) http: //www .wangshibo.com$1/; break ; } 針對(duì)站點(diǎn)根目錄下的某個(gè)子目錄作鏡向 配置如下:就會(huì)把http: //www .huanqiu.com的內(nèi)容(即首頁)鏡像到 /var/www/html 下的ops目錄下了 server { listen 80; server_name www.wangshibo.com; root /var/www/html ; location ^~ /ops { rewrite ^.+ http: //www .huanqiu.com/ last; break ; } index index.html index.php index.htm; access_log /usr/local/nginx/logs/image .log; } 域名鏡像(其實(shí)就是域名跳轉(zhuǎn)) server { listen 80; server_name www.wangshibo.com; root /var/www/html ; rewrite ^/(.*) http: //www .huanqiu.com/$1 last; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image .log; } 其他: rewrite ^/(space|network)-(.+)\.html$ /$1.php?rewrite=$2 last; rewrite ^/(space|network)\.html$ /$1.php last; rewrite ^/([0-9]+)$ /space .php?uid=$1 last; rewrite ^(.*) /archiver/ ((fid|tid)-[\w\-]+\.html)$ $1 /archiver/index .php?$2 last; rewrite ^(.*) /forum- ([0-9]+)-([0-9]+)\.html$ $1 /forumdisplay .php?fid=$2&page=$3 last; rewrite ^(.*) /thread- ([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1 /viewthread .php?tid=$2&extra=page\%3D$4&page=$3 last; rewrite ^(.*) /profile- (username|uid)-(.+)\.html$ $1 /viewpro .php?$2=$3 last; rewrite ^(.*) /space- (username|uid)-(.+)\.html$ $1 /space .php?$2=$3 last; rewrite ^(.*) /tag- (.+)\.html$ $1 /tag .php?name=$2 last; |
目錄對(duì)換:/1234/xxx ----->xxx?id=1234
配置如下:
[root@test-huanqiu ~]# vim /usr/local/nginx/conf/vhosts/test.conf
server {
listen 80;
server_name www.wangshibo.com;
root /var/www/html;
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
[root@test-huanqiu ~]# cat /var/www/html/ops/index.html
nginx的目錄對(duì)換的跳轉(zhuǎn)測(cè)試
如上配置后,那么:
訪問http://www.wangshibo.com/?id=567567567567567 的結(jié)果就是http://www.wangshibo.com/的結(jié)果
訪問http://www.wangshibo.com/ops/?id=wangshibo 的結(jié)果就是http://www.wangshibo.com/ops的結(jié)果
訪問http://www.wangshibo.com/wang/?id=123111 的結(jié)果就是http://www.wangshibo.com/wang的結(jié)果
.......
2.反向代理(proxy_pass)
簡(jiǎn)單測(cè)試nginx反向代理和負(fù)載均衡功能的操作記錄(1)-----http代理
簡(jiǎn)單測(cè)試nginx反向代理和負(fù)載均衡功能的操作記錄(2)-----https代理
3.緩存設(shè)置
nginx反向代理+緩存開啟+url重寫+負(fù)載均衡(帶健康探測(cè))的部署記錄
nginx緩存配置的操作記錄梳理
4.防盜鏈。關(guān)于Nginx防盜鏈具體設(shè)置,可參考:Nginx中防盜鏈(下載防盜鏈和圖片防盜鏈)的操作記錄
location ~* \.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}
下面設(shè)置文件反盜鏈并設(shè)置過期時(shí)間:
location ~*^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
valid_referers none blocked *.wangshibo.com*.wangshibo.net localhost 218.197.67.14;
if ($invalid_referer) {
rewrite ^/ http://img.wangshibo.net/leech.gif;
return 412;
break;
}
access_log off;
root /opt/lampp/htdocs/web;
expires 3d;
break;
}
這里的return 412 是自定義的http狀態(tài)碼,默認(rèn)為403,方便找出正確的盜鏈的請(qǐng)求
“rewrite ^/ http://img.wangshibo.net/leech.gif;”顯示一張防盜鏈圖片
“access_log off;”不記錄訪問日志,減輕壓力
“expires 3d”所有文件3天的瀏覽器緩存
5.根據(jù)文件類型設(shè)置過期時(shí)間
1)expires起到控制頁面緩存的作用,合理的配置expires可以減少很多服務(wù)器的請(qǐng)求;
2)對(duì)于站點(diǎn)中不經(jīng)常修改的靜態(tài)內(nèi)容(如圖片,JS,CSS),可以在服務(wù)器中設(shè)置expires過期時(shí)間,控制瀏覽器緩存,達(dá)到有效減小帶寬流量,降低服務(wù)器壓力的目的。
3)Expires是Web服務(wù)器響應(yīng)消息頭字段,在響應(yīng)http請(qǐng)求時(shí)告訴瀏覽器在過期時(shí)間前瀏覽器可以直接從瀏覽器緩存取數(shù)據(jù),而無需再次請(qǐng)求。
要配置expires,可以在http段中或者server段中或者location段中加入;
如下:控制圖片等過期時(shí)間為30天,如果圖片文件不怎么更新,過期可以設(shè)大一點(diǎn);如果頻繁更新,則可以設(shè)置得小一點(diǎn),具體視情況而定
location ~ \.(gif|jpg|jpeg|png|bmp|swf|ico)$ {
root /var/www/img/;
expires 30d;
}
location ~ .*\.(js|css)$ {
expires 10d;
}
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
expires 1h;
break;
}
}
location ~ \.(wma|wmv|asf|mp3|mmf|zip|rar|swf|flv)$ {
root /var/www/upload/;
expires max;
}
expires 指令可以控制 HTTP 應(yīng)答中的“ Expires ”和“ Cache-Control ”的頭標(biāo)(起到控制頁面緩存的作用)
語法:expires [time|epoch|max|off]
默認(rèn)值:off
expires指令控制HTTP應(yīng)答中的“Expires”和“Cache-Control”Header頭部信息,啟動(dòng)控制頁面緩存的作用
time:可以使用正數(shù)或負(fù)數(shù)?!癊xpires”頭標(biāo)的值將通過當(dāng)前系統(tǒng)時(shí)間加上設(shè)定time值來設(shè)定。
time值還控制"Cache-Control"的值:
負(fù)數(shù)表示no-cache
正數(shù)或零表示max-age=time
epoch:指定“Expires”的值為 1 January,1970,00:00:01 GMT
max:指定“Expires”的值為31 December2037 23:59:59GMT,"Cache-Control"的值為10年。(即設(shè)置過期時(shí)間最最長(zhǎng))
-1:指定“Expires”的值為當(dāng)前服務(wù)器時(shí)間-1s,即永遠(yuǎn)過期。
off:不修改“Expires”和"Cache-Control"的值
expires使用了特定的時(shí)間,并且要求服務(wù)器和客戶端的是中嚴(yán)格同步。
而Cache-Control是用max-age指令指定組件被緩存多久。
對(duì)于不支持http1.1的瀏覽器,還是需要expires來控制。所以最好能指定兩個(gè)響應(yīng)頭。但HTTP規(guī)范規(guī)定max-age指令將重寫expires頭。
如何檢測(cè)nginx中設(shè)置的expires網(wǎng)頁過期時(shí)間是否生效?
方法:
打開webkaka的網(wǎng)站速度診斷工具(http://pagespeed.webkaka.com/),輸入你的網(wǎng)頁地址,檢測(cè)后,立即可以看到設(shè)置是否生效了。如下圖所示:
上圖可以看到,被檢測(cè)網(wǎng)頁的js文件過期時(shí)間為1天(12h)。
6.禁止訪問某個(gè)文件或目錄
1)禁止訪問以txt或doc結(jié)尾的文件
location ~* \.(txt|doc)${
root /data/www/wwwroot/linuxtone/test;
deny all;
}
2)nginx禁止訪問所有.開頭的隱藏文件設(shè)置
location ~* /.* {
deny all;
}
3)nginx禁止訪問目錄
location ^~ /path {
deny all;
}
4)禁止訪問擴(kuò)展名為bat的文件
location ~* /.bat {
deny all;
}
5)禁止訪問configs目錄,以及其下所有子目錄或文件
location ^~ /configs/ {
deny all;
}
注意上述configs后面的斜杠不能少,否則所有以configs開頭的目錄或文件都將禁止訪問。
6)禁止訪問多個(gè)目錄
location ~ ^/(cron|templates)/ {
deny all;
break;
}
7)禁止訪問以/data開頭的文件
location ~ ^/data {
deny all;
}
8)禁止訪問以.sh,.flv,.mp3為文件后綴名的文件
location ~ .*\.(sh|flv|mp3)$ {
return 403;
}
9)或者以=符號(hào)形式
location = /config/ {
return 404;
}
location =/config.ini{
return 404;
}
10)禁止htaccess
location ~/\.ht {
deny all;
}
return指令
語法:returncode ;
使用環(huán)境:server,location,if;
該指令用于結(jié)束規(guī)則的執(zhí)行并返回狀態(tài)碼給客戶端。
例如:訪問的URL以".sh"或".bash"結(jié)尾,則返回403狀態(tài)碼
location ~ .*\.(sh|bash)?$ {
return 403;
}
7.禁止IP訪問 只允許域名訪問
當(dāng)別人通過ip或者未知域名訪問你的網(wǎng)站的時(shí)候,你希望禁止顯示任何有效內(nèi)容,可以給他返回500.
目前國(guó)內(nèi)很多機(jī)房都要求網(wǎng)站主關(guān)閉空主機(jī)頭,防止未備案的域名指向過來造成麻煩。
為了避免網(wǎng)站遭受惡意IP攻擊,需要禁止IP訪問,只能使用域名訪問站點(diǎn)!
listen行加上default(或default_server)參數(shù),表示這個(gè)是默認(rèn)虛擬主機(jī)。
所以,禁止ip訪問,只能使用域名訪問的正確配置是:
server {
listen 80 default_server;
server_name _;
return 500;
}
server {
listen 80;
server_name web01.wangshibo.cn;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
注意:
如果在上面的server_name配置中指定域名的同時(shí),也指明了ip訪問,比如server_name 103.110.186.17 web01.wangshibo.cn
那么盡管上面已經(jīng)做了返回500設(shè)置,也禁止不了ip訪問!也就是說,只要server_name一行指明了ip訪問,那么就禁止不了了。
以上設(shè)置,可以將ip訪問禁用,這樣的話,使用ip訪問的流量就會(huì)丟失。
如果想把這部分流量收集起來,導(dǎo)入到自己的網(wǎng)站,只要做以下跳轉(zhuǎn)設(shè)置就可以:
server {
listen 80 default;
rewrite ^(.*) http://www.wangshibo.com permanent;
}
server {
listen 80;
server_name web01.wangshibo.cn;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
下面列出其他的一些細(xì)節(jié)導(dǎo)致的不同效果:
1)將ip和域名訪問統(tǒng)統(tǒng)禁止,返回403(或者配置return 500)錯(cuò)誤頁
server {
listen 80 default_server;
server_name _;
return 403;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
2)下面的配置:
指明了只能使用域名,即http://web01.wangshibo.cn訪問配置中的站點(diǎn)(/var/www/html)
不能使用ip,即http://103.110.186.17訪問配置中的站點(diǎn)。但是可以使用ip方式訪問nginx默認(rèn)的根目錄下的內(nèi)容(比如/usr/local/nginx/html)
server {
listen 80 ;
server_name web01.wangshibo.cn;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
下面的配置,指明了使用域名或ip都可以訪問配置中的站點(diǎn)。(使用ip訪問只限于只有一個(gè)vhost虛擬主機(jī)配置的情況,如果是多個(gè),那么指明ip訪問就會(huì)混淆)
server {
listen 80 ;
server_name 103.110.186.17 web01.wangshibo.cn;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
3)下面兩個(gè)的配置后,都能使用域名或ip訪問配置中的站點(diǎn)。
server {
listen 80 default;
server_name web01.wangshibo.cn;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
server {
listen 80 default;
server_name 103.110.186.17 web01.wangshibo.cn;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
8.流量限制
對(duì)于提供下載的網(wǎng)站,肯定是要進(jìn)行流量控制的,例如BBS、視頻服務(wù),還是其它專門提供下載的網(wǎng)站。在nginx中我們完全可以做到限流,由Nginx模塊中的Core模塊提供了limit_rate、limit_rate_after命令,我們只需要調(diào)用命令實(shí)現(xiàn)流量限制就行。
實(shí)現(xiàn)流量限制由兩個(gè)指令limit_rate和limit_rate_after共同完成:
limit_rate
語法: limit_rate rate;
默認(rèn)值: limit_rate 0;
作用域: http, server, location, location中的if字段
命令概述:限制向客戶端傳送響應(yīng)的速率限制。參數(shù) rate 的單位是字節(jié)/秒,設(shè)置為 0 將關(guān)閉限速。 nginx 按連接限速,需要明白的一點(diǎn)是該限制只是針對(duì)一個(gè)連接的設(shè)定,所以如果某個(gè)客戶端同時(shí)開啟了兩個(gè)連接,那么客戶端的整體速率是這條指令設(shè)置值的2倍。
limit_rate_after
語法: limit_rate_after size;
默認(rèn)值: limit_rate_after 0;
作用域:http, server, location,location中的if字段
設(shè)置不限速傳輸?shù)捻憫?yīng)大小。當(dāng)傳輸量大于此值時(shí),超出部分將限速傳送。
示例說明:
server {
listen 80;
server_name ops.wangshibo.com;
location /ops/{
root /home/www/html;
limit_rate_after 5m;
limit_rate 20k;
}
}
測(cè)試:
[root@test-huanqiu ~]# wget http://ops.wangshibo.com/ops/seven.mp4
修改配置之前,速率沒有限制:
修改配置之后,可見由于傳輸量大于5m,超出部分的傳輸速率已經(jīng)被限制在20k/s:
可以發(fā)現(xiàn)配置之后,剛開始的時(shí)候傳輸速度很高,因?yàn)?,傳輸量大于設(shè)定值的部分才會(huì)受到限制。這就說明,我們兩個(gè)命令都發(fā)揮了作用!
9.并發(fā)連接數(shù)限制
這個(gè)配置是基于ngx_http_limit_zone_module模塊的,要簡(jiǎn)單完成并發(fā)限制,我們要涉及到limit_conn_zone和limit_conn 這兩個(gè)指令:
limit_conn_zone
語法:limit_conn_zone zone_name $variable the_size
默認(rèn)值:no
作用域:http
本指令定義了一個(gè)數(shù)據(jù)區(qū),里面記錄會(huì)話狀態(tài)信息。 variable 定義判斷會(huì)話的變量;the_size 定義記錄區(qū)的總?cè)萘俊?/p>
limit_conn
語法:limit_conn zone_name the_size
默認(rèn)值:no
作用域:http, server, location
指定一個(gè)會(huì)話最大的并發(fā)連接數(shù)。 當(dāng)超過指定的最發(fā)并發(fā)連接數(shù)時(shí),服務(wù)器將返回 "Service unavailable" (503)。
示例說明:
http {
limit_conn_zone $binary_remote_addr zone=one:10m;
.......
.......
server {
listen 80;
server_name ops.wangshibo.com;
location /ops/ {
limit_conn one 1;
}
示例解釋:
1)定義一個(gè)叫“one”的記錄區(qū),總?cè)萘繛?10M,以變量$binary_remote_addr作為會(huì)話的判斷基準(zhǔn)(即一個(gè)地址一個(gè)會(huì)話)。
限制/ops/目錄下,一個(gè)會(huì)話只能進(jìn)行一個(gè)連接;簡(jiǎn)單來說,就是限制/ops/目錄下,一個(gè)IP只能發(fā)起一個(gè)連接,多過一個(gè),一律報(bào)錯(cuò)503。
2)這里使用的是$binary_remote_addr而不是 $remote_addr。$remote_addr的長(zhǎng)度為7至15 bytes,會(huì)話信息的長(zhǎng)度為32或64bytes;而 $binary_remote_addr的長(zhǎng)度為4bytes,會(huì)話信息的長(zhǎng)度為32bytes;$binary_remote_addr是限制同一客戶端ip地址;當(dāng) zone 的大小為 1M 的時(shí)候,大約可以記錄 32000 個(gè)會(huì)話信息(一個(gè)會(huì)話占用 32 bytes)。
下面分享一個(gè)限制流量和并發(fā)送的配置:
現(xiàn)象描述:
中間一段時(shí)間,網(wǎng)站訪問有點(diǎn)慢,初步懷疑是機(jī)房交換機(jī)問題(之前出現(xiàn)過網(wǎng)站訪問很慢,熱插拔網(wǎng)卡/重啟網(wǎng)卡就好了)
最后查看,發(fā)現(xiàn)機(jī)房流量很大!主要是論壇流量大,主站流量很小,應(yīng)該是論壇人數(shù)訪問一多,就把帶寬占滿了。
解決辦法:
在論壇服務(wù)器上修改:
1)首先限制并發(fā)數(shù)
[root@server_web ~]# vim /etc/sysconfig/iptables
.....
-A INPUT -p tcp --dport 80 -m limit --limit 6/s -j ACCEPT
[root@server_web ~]# /etc/init.d/iptables restart
上面將每個(gè)用戶限制在每秒6個(gè)請(qǐng)求,但效果不明顯。
2)設(shè)置nginx的流量請(qǐng)求
[root@server_web ~]# vim /usr/local/nginx/conf/nginx.conf
http{
limit_conn_zone $binary_remote_addr zone=perip:10m;
# limit_req_zone $binary_remote_addr zone=one2:10m rate=5r/s;
# limit_req zone=one2 burst=5;
..........
..........
}
[root@server_web ~]# vim /usr/local/nginx/conf/vhost/forum.conf
server {
listen 80;
server_name forum.wangshibo.com;
root /var/www/html;
limit_conn perip 10; //這里調(diào)用上面的perip,需要寫在server里面;即每個(gè)ip最多有10個(gè)并發(fā)連接
limit_rate 10k; //限制每個(gè)連接的帶寬,可以單獨(dú)寫這條,與連接數(shù)無關(guān);
}
}
[root@server_web ~]# /usr/local/nginx/sbin/nginx -s reload
10.nginx的訪問控制及DDOS預(yù)防
1)訪問控制配置
基于各種原因,Ningx有時(shí)要進(jìn)行訪問控制。
比如說,一般網(wǎng)站的后臺(tái)都不能讓外部訪問,所以要添加 IP 限制,通常只允許公司的IP訪問。
訪問控制就是指只有符合條件的IP才能訪問到這個(gè)網(wǎng)站的某個(gè)區(qū)域。
涉及模塊:ngx_http_access_module
模塊概述:允許限制某些 IP 地址的客戶端訪問。
對(duì)應(yīng)指令:
allow
語法: allow address | CIDR | unix: | all;
默認(rèn)值: —
作用域: http, server, location, limit_except
允許某個(gè) IP 或者某個(gè) IP 段訪問。如果指定 unix,那將允許 socket 的訪問。注意:unix 在 1.5.1 中新加入的功能,如果你的版本比這個(gè)低,請(qǐng)不要使用這個(gè)方法。
deny
語法: deny address | CIDR | unix: | all;
默認(rèn)值: —
作用域: http, server, location, limit_except
禁止某個(gè) IP 或者一個(gè) IP 段訪問。如果指定 unix,那將禁止 socket 的訪問。注意:unix 在 1.5.1 中新加入的功能,如果你的版本比這個(gè)低,請(qǐng)不要使用這個(gè)方法。
示例說明:
server {
listen 80;
server_name forum.wangshibo.com;
root /var/www/html;
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 103.10.67.56;
deny all;
}
}
規(guī)則按照順序依次檢測(cè),直到匹配到第一條規(guī)則。
在這個(gè)例子里,只有 10.1.1.0/16 、192.168.1.0/24和103.10.67.56允許訪問,但 192.168.1.1 除外。
如下實(shí)例:
1)先是多域名綁定一個(gè)目錄后的301跳轉(zhuǎn)至同一個(gè)域名
2)針對(duì)網(wǎng)站訪問做來源ip白名單設(shè)置,并加上密碼。(即用戶認(rèn)證配置)
[root@test-huanqiu vhosts]# cat test.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | server { listen 80; server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com; if ($host != 'www.wangshibo.com' ) { rewrite ^/(.*)$ http: //www .wangshibo.com/$1 permanent; } root /var/www/html ; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image .log; allow 192.168.1.0 /24 ; allow 124.65.197.154; deny all; auth_basic "C1G_ADMID" ; auth_basic_user_file /usr/local/nginx/htpasswd ; } |
[root@test-huanqiu vhosts]# htpasswd -c /usr/local/nginx/htpasswd wangshibo
New password:
Re-type new password:
Adding password for user wangshibo
訪問站點(diǎn)http://www.wangshibo.com,效果如下:
ngx_http_access_module 配置允許的地址能訪問,禁止的地址被拒絕。這只是很簡(jiǎn)單的訪問控制,而在規(guī)則很多的情況下,使用 ngx_http_geo_module 模塊變量更合適。
這個(gè)模塊大家下來可以了解 : ngx_http_geo_module
-------------------------------------------------------------------------------------------------------
上面也用到了nginx的用戶認(rèn)證的配置,其中:
auth_basic 認(rèn)證時(shí)的提示信息
auth_basic_user_file 認(rèn)證時(shí)存放用戶名和密碼的文件
# htpasswd -c /usr/local/nginx/htpasswd wangshibo //第一次設(shè)置認(rèn)證的用戶
# htpasswd /usr/local/nginx/htpasswd guohuihui //追加認(rèn)證的用戶,后面再次追加認(rèn)證用戶時(shí),不要加-c參數(shù),否則就會(huì)覆蓋之前添加的用戶!
下面順便看幾個(gè)認(rèn)證部分的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | location /admin/ { auth_basic "Admin Auth." ; auth_basic_user_file /usr/local/nginx/htpasswd ; } location /wangshibo/ { proxy_pass http: //www .guohuihui.com /heng/ ; auth_basic "Test Auth." ; auth_basic_user_file /usr/local/nginx/htpasswd ; } location ^~ /auth/ { location ~ .*.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; } auth_basic "Authorized users only" ; auth_basic_user_file /usr/local/nginx/htpasswd ; } |
2)DDOS預(yù)防配置
DDOS的特點(diǎn)是分布式,針對(duì)帶寬和服務(wù)攻擊,也就是四層流量攻擊和七層應(yīng)用攻擊,相應(yīng)的防御瓶頸四層在帶寬,七層的多在架構(gòu)的吞吐量。
對(duì)于七層的應(yīng)用攻擊,還是可以做一些配置來防御的,使用nginx的http_limit_conn和http_limit_req模塊通過限制連接數(shù)和請(qǐng)求數(shù)能相對(duì)有效的防御。
其中:
ngx_http_limit_conn_module 可以限制單個(gè) IP 的連接數(shù)
ngx_http_limit_req_module 可以限制單個(gè) IP 每秒請(qǐng)求數(shù)
配置方法:
(1)限制每秒請(qǐng)求數(shù),即ip訪問頻率限制
涉及模塊:ngx_http_limit_req_module
通過漏桶原理來限制單位時(shí)間內(nèi)的請(qǐng)求數(shù),一旦單位時(shí)間內(nèi)請(qǐng)求數(shù)超過限制,就會(huì)返回 503 錯(cuò)誤。
配置范例:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;
...
server {
...
location ~ \.php$ {
limit_req zone=one burst=5 nodelay;
}
}
}
配置說明(上一部分解釋過的就不再解釋):
定義一個(gè)名為one的limit_req_zone用來存儲(chǔ)session,大小是10M內(nèi)存,
以$binary_remote_addr 為key,限制平均每秒的請(qǐng)求為20個(gè),
1M能存儲(chǔ)16000個(gè)狀態(tài),rete的值必須為整數(shù),
rate=20r/s表示限制頻率為每秒20個(gè)請(qǐng)求;如果限制兩秒鐘一個(gè)請(qǐng)求,可以設(shè)置成30r/m。
限制每ip每秒不超過20個(gè)請(qǐng)求,漏桶數(shù)burst為5
brust的意思就是,如果第1秒、2,3,4秒請(qǐng)求為19個(gè),
第5秒的請(qǐng)求為25個(gè)是被允許的。
但是如果你第1秒就25個(gè)請(qǐng)求,第2秒超過20的請(qǐng)求返回503錯(cuò)誤。
nodelay,如果不設(shè)置該選項(xiàng),嚴(yán)格使用平均速率限制請(qǐng)求數(shù),
第1秒25個(gè)請(qǐng)求時(shí),5個(gè)請(qǐng)求放到第2秒執(zhí)行,
設(shè)置nodelay,25個(gè)請(qǐng)求將在第1秒執(zhí)行。
(2)限制IP連接數(shù)(上面已經(jīng)說明,這里直接寫配置)
http {
limit_conn_zone $binary_remote_addr zone=addr:10m; //上面講過
...
server {
...
location /ops/ {
limit_conn addr 1;
}
}
}
總的來說:如何設(shè)置能限制某個(gè)IP某一時(shí)間段的訪問次數(shù)是一個(gè)讓人頭疼的問題,特別面對(duì)惡意的ddos攻擊的時(shí)候。其中CC攻擊(Challenge Collapsar)是DDOS(分布式拒絕服務(wù))的一種,也是一種常見的網(wǎng)站攻擊方法,攻擊者通過代理服務(wù)器或者肉雞向向受害主機(jī)不停地發(fā)大量數(shù)據(jù)包, 造成對(duì)方服務(wù)器資源耗盡,一直到宕機(jī)崩潰。
cc攻擊一般就是使用有限的ip數(shù)對(duì)服務(wù)器頻繁發(fā)送數(shù)據(jù)來達(dá)到攻擊的目的。
nginx可以通過Http LimitReq Modul和Http LimitZone Module配置來限制ip在同一時(shí)間段的訪問次數(shù)來防cc攻擊。
1)Http LimitReq Modul用來限制連單位時(shí)間內(nèi)連接數(shù)的模塊,使用limit_req_zone和limit_req指令配合使用來達(dá)到限制。一旦并發(fā)連接超過指定數(shù)量,就會(huì)返回503錯(cuò)誤。
2)Http LimitConn Modul用來限制單個(gè)ip的并發(fā)連接數(shù),使用limit_zone和limit_conn指令
配置示例:
Http LimitReq Modul限制某一段時(shí)間內(nèi)同一ip訪問數(shù)
http{
......
limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
......
server{
...
location {
......
limit_req zone=allips burst=5 nodelay;
......
}
......
}
......
}
Http LimitZone Module 限制并發(fā)連接數(shù)實(shí)例
limit_zone只能定義在http作用域,limit_conn可以定義在http server location作用域
http{
...
limit_conn_zone one $binary_remote_addr 10m;
......
server{
......
location {
......
limit_conn one 20;
limit_rate 500k;
......
}
......
}
......
}
(3)限速白名單設(shè)置(可參考:nginx利用geo模塊做限速白名單以及geo實(shí)現(xiàn)全局負(fù)載均衡的操作記錄)
http_limit_conn和 http_limit_req模塊限制了單IP單位時(shí)間內(nèi)的連接和請(qǐng)求數(shù),但是如果Nginx前面有l(wèi)vs或者h(yuǎn)aproxy之類的負(fù)載均衡或者反向代理,nginx 獲取的都是來自負(fù)載均衡的連接或請(qǐng)求,這時(shí)不應(yīng)該限制負(fù)載均衡的連接和請(qǐng)求,就需要 geo 和 map 模塊設(shè)置白名單:
geo $whiteiplist {
default 1;
10.11.15.1610;
}
map $whiteiplist$limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=one:10m rate=10r/s;
limit_conn_zone $limit zone=addr:10m;
geo 模塊定義了一個(gè)默認(rèn)值是 1 的變量 whiteiplist,當(dāng)在 ip 在白名單中,變量 whiteiplist 的值為 0,反之為1.
對(duì)上面設(shè)置的邏輯關(guān)系解釋:
如果在白名單中--> whiteiplist=0 --> $limit="" --> 不會(huì)存儲(chǔ)到 10m 的會(huì)話狀態(tài)(one 或者 addr)中 --> 不受限制;
反之,不在白名單中 --> whiteiplist=1 --> $limit=二進(jìn)制遠(yuǎn)程地址 -->存儲(chǔ)進(jìn) 10m 的會(huì)話狀態(tài)中 --> 受到限制。
(4)動(dòng)手測(cè)試DDOS預(yù)防配置
下面來測(cè)一下上面說到的配置是否起到了作用。
安裝nginx+php環(huán)境
寫一個(gè)測(cè)試的PHP文件,修改nginx配置文件,使其能正常訪問。
在/home/shiyanlou目錄下寫一個(gè)test.php,內(nèi)容如下:
[root@server_web1 ~]# vim /home/shiyanlou/test.php
<?php
phpinfo ();
?>
nginx 配置文件修改:
最后展示:
使ab命令進(jìn)行測(cè)試,比較修改nginx配置文件前后(連接數(shù)和請(qǐng)求數(shù)分開測(cè)試)的測(cè)試結(jié)果。
修改之前:
測(cè)試結(jié)果為:
對(duì)nginx配置做修改(添加http和php配置如下的紅線內(nèi)容),重啟,然后再進(jìn)行測(cè)試
測(cè)試結(jié)果為:
11.訪問白名單
參考:nginx訪問白名單設(shè)置以及根據(jù)$remote_addr分發(fā)
12.nginx的上傳下載設(shè)置
參考:nginx限制上傳大小和超時(shí)時(shí)間設(shè)置說明/php限制上傳大小
13.nginx目錄瀏覽及其驗(yàn)證功能
參考:nginx下目錄瀏覽及其驗(yàn)證功能配置記錄
14.Nginx下禁止指定目錄運(yùn)行php腳本文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 非常簡(jiǎn)單,直接通過location條件匹配定位后進(jìn)行權(quán)限禁止。 在server配置段中增加下面的的配置: 1)如果是單個(gè)目錄 location ~* ^ /uploads/ .*\.(php|php5)$ { deny all; } 2)如果是多個(gè)目錄 location ~* ^/(attachments|uploads)/.*\.(php|php5)$ { deny all; } 注意:這段配置文件一定要放在下面配置的前面才可以生效。 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } 配置完后記得重啟Nginx生效。 ------------------------------------------------------------------------------ 如果是Apache下禁止指定目錄運(yùn)行PHP腳本,在虛擬主機(jī)配置文件中增加php_flag engine off指令即可,配置如下 "/website/uploads" > Options FollowSymLinks AllowOverride None Order allow,deny Allow from all php_flag engine off |
聯(lián)系客服