在linux系統下使用nginx做爲web應用服務,用來提高網站訪問速度的經驗已五年多了,今天在此對nginx的使用作一簡單總結。php
1、nginx服務簡介
Nginx是一個高性能的HTTP和反向代理服務器,也是一個 IMAP/POP3/SMTP代理服務器。Nginx 已經由於它的穩定性、豐富的功能集、示例配置文件和低系統資源的消耗而聞名了。css
使用 Nginx 前必須瞭解的事項:
1)目前官方 Nginx 並不支持 Windows,您只能在包括 Linux、UNIX、BSD 系統下安裝和使用;
2)Nginx 自己只是一個 HTTP 和反向代理服務器,它沒法像 Apache 同樣經過安裝各類模塊來支持不一樣的頁面腳本,例如 PHP、CGI 等;
3)Nginx 支持簡單的負載均衡和容錯;
4)支持做爲基本 HTTP 服務器的功能,例如日誌、壓縮、Byte ranges、Chunked responses、SSL、虛擬主機等等,應有盡有。html
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方便開發和擴展,也正所以才使得Nginx功能如此強大。Nginx的模塊默認編譯進nginx中,若是須要增長或刪除模塊,須要從新編譯Nginx,這一點不如Apache的動態加載模塊方便。若是有須要動態加載模塊,可使用由淘寶網發起的web服務器Tengine,在nginx的基礎上增長了不少高級特性,徹底兼容Nginx,已被國內不少網站採用。前端
Nginx處理鏈接過程:
nginx不會爲每一個鏈接派生進程或線程,而是由 worker 進程經過監聽共享套接字接受新請求,而且使用高效的循環來處理數千個鏈接。Nginx 不使用仲裁器或分發器來分發鏈接,這個工做由操做系統內核機制完成。監聽套接字在啓動時就完成初始化,worker 進程經過這些套接字接受、讀取請求和輸出響應。java
Nginx的工做模式很簡單,就是採用一個master進程和多個worker工做進程:
其中master進程的做用也是很明確的就是負責管理worker進程,同時監聽鏈接請求,當鏈接請求到來以後將鏈接放入worker進程中去處理具體的業務請求,好比說http請求。 Nginx可以處理高併發的緣由在於對socket的管理方式是異步非阻塞的,使用select/poll/epoll/kqueue 來實現對大量socket描述符的管理,每一個worker進程有一個主線程,而沒有其餘的線程這樣的好處就在於不須要進行線程間的切換,這樣就節省了資源。因此總的來講:Nginx可以實現支持高併發的同時運行效率還很低的關鍵在於整個系統內部只有有限的幾個工做進程和一個監聽進程,而每一個進程內部只有一個主線程,這樣就不會引發不少的線程切換,從而下降了系統開銷,同時每一個線程內部使用異步非阻塞的方式來管理描述符這樣就能夠管理大量的描述符,當描述符多的時候也只是會佔用較多的內存而已,而不會形成佔用大量cpu時間。以上說的就是Nginx的進程模型和事件模型,事件模型中處理的狀況主要有三種,分別是網絡事件,如HTTP請求等,網絡事件使用異步非阻塞模式就能夠很好的解決;還有信號,定時器,信號和定時器還不是很明白。Nginx處理進程間爭奪系統資源的方式:也就是進程間存在的驚羣現象。node
master:
當 nginx 在啓動後,會有一個 master 進程和多個 worker 進程。master進程主要用來管理worker進程,master 要作的就是:接收來自外界的信號,向各 worker 進程發送信號,監控 worker 進程的運行狀態,當 worker 進程退出後(異常狀況下),會自動從新啓動新的 worker 進程。
主要完成以下工做:
1)讀取並驗證配置信息;
2)建立、綁定及關閉套接字;
3)啓動、終止 worker 進程及維護 worker 進程的個數;
4)無須停止服務而從新配置工做;
5)控制非中斷式程序升級,啓用新的二進制程序並在須要時回滾至老版本;
6)從新打開日誌文件;
7)編譯嵌入式perl腳本linux
worker:
對於基本的網絡事件,則是放在 worker 進程中來處理了。多個 worker 進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個 worker 進程中處理,一個 worker 進程,不可能處理其它進程的請求(一對一)。然而 nginx 沒有專門地仲裁或鏈接分佈的 worker,這項工做是由操做系統內核機制完成的。在啓動時,建立一組初始的監聽套接字,HTTP 請求和響應之時,worker 連續接收、讀取和寫入套接字。
worker 進程主要完成的任務包括:
1)接收、傳入並處理來自客戶端的鏈接;
2)提供反向代理及過濾功能;
3)nginx任何能完成的其它任務nginx
舉例說明一個完整請求如何經過互相協做來實現的:
既然worker進程之間是平等的,每一個進程,處理請求的機會也是同樣的。當咱們提供80端口的http服務時,一個鏈接請求過來,每一個進程都有可能處理這個鏈接。那麼問題來了,到底最後怎樣處理,是由什麼決定的呢?首先,每一個 worker 進程都是從 master 進程 fork 過來,在 master 進程裏面,先創建好須要 listen 的 socket(listenfd)以後,而後再 fork 出多個 worker 進程。全部 worker 進程的 listenfd 會在新鏈接到來時變得可讀,爲保證只有一個進程處理該鏈接,全部 worker 進程會在註冊 listenfd 讀事件前搶 accept_mutex,搶到互斥鎖的那個進程註冊 listenfd 讀事件,而後在讀事件裏調用 accept 接受該鏈接。當一個 worker 進程在 accept 這個鏈接以後,就開始讀取請求、解析請求、處理請求。產生數據後,再返回給客戶端,最後才斷開鏈接,這樣一個完整的請求就是這樣的了。咱們能夠看到:一個請求,徹底由 worker 進程來處理,並且只在一個 worker 進程中處理。web
也許有個疑問,那就是nginx採用多worker 的方式來處理請求,每一個 worker 裏面只有一個主線程,那可以處理的併發數頗有限啊,多少個 worker 就能處理多少個併發,何來高併發呢?
然而,這就是 nginx 的高明之處,nginx 採用了異步非阻塞的方式來處理請求,也就是說,nginx 是能夠同時處理成千上萬個請求的。正則表達式
異步非阻塞
異步的概念是和同步相對的,也就是不一樣事件之間不是同時發生的。非阻塞的概念是和阻塞對應的,阻塞是事件按順序執行,每一事件都要等待上一事件的完成,而非阻塞是若是事件沒有準備好,這個事件能夠直接返回,過一段時間再進行處理詢問,這期間能夠作其餘事情。
2、nginx相對於傳統的apache服務的優缺點
nginx相對比apache,實在有太多的優點。能夠說,如今Nginx纔是Web服務器的首選!!
1)nginx相對於apache的優勢:
輕量級,一樣起web 服務,比apache 佔用更少的內存及資源;
抗併發,nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能;
高度模塊化的設計,編寫模塊相對簡單;
社區活躍,各類高性能模塊出品迅速;
固然apache相對於nginx也有它自身的優勢:rewrite比nginx 的rewrite強大;模塊超多,基本想到的均可以找到;少bug,nginx的bug相對較多;超穩定;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)nginx處理動態請求是雞肋,通常動態請求要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更好。
3、在 Linux 下安裝 Nginx
爲了確保能在Nginx中使用正則表達式進行更靈活的配置,安裝以前須要肯定系統是否安裝有PCRE(Perl Compatible Regular Expressions)包。
您能夠到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 通常有兩個版本,分別是穩定版和開發版,您能夠根據您的目的來選擇這兩個版本的其中一個,下面是把 Nginx 安裝到 /opt/nginx 目錄下的詳細步驟:
# 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
其中參數 --with-http_stub_status_module 是爲了啓用 nginx 的 NginxStatus 功能,用來監控 Nginx 的當前狀態。
安裝成功後/opt/nginx 目錄下有四個子目錄分別是:conf、html、logs、sbin 。
其中Nginx的配置文件存放於conf/nginx.conf,Nginx只有一個程序文件位於sbin目錄下的nginx文件。
確保系統的80端口沒被其餘程序佔用,運行sbin/nginx命令來啓動Nginx,打開瀏覽器訪問此機器的 IP,若是瀏覽器出現 Welcome to nginx! 則表示 Nginx 已經安裝並運行成功。
經常使用的 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 進行控制
Nginx 支持下表中的信號:
有兩種方式來經過這些信號去控制Nginx:
第一是經過logs目錄下的nginx.pid查看當前運行的Nginx的進程ID,經過 kill – XXX <pid> 來控制 Nginx,其中 XXX 就是上表中列出的信號名。
若是系統中只有一個Nginx進程,那也能夠經過 killall 命令來完成,例如運行 killall – s HUP nginx 來讓 Nginx 從新加載配置。
配置 Nginx
先來看一個實際的配置文件:
user nobody;# 工做進程的屬主 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 都會很是及時的處理狀態的變化,以保證不會影響到用戶的訪問。
Nginx的location語法規則:location [=|~|~*|^~] /uri/ { … }
= 開頭表示精確匹配
^~ 開頭表示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整個程序包只有500多K,但麻雀雖小、五臟俱全。 Nginx官方提供的各類功能模塊應有盡有,結合這些模塊能夠完整各類各樣的配置要求,例如:壓縮、防盜鏈、集羣、FastCGI、流媒體服務器、Memcached 支持、URL 重寫等等,更關鍵的是Nginx擁有Apache和其餘HTTP服務器沒法比擬的高性能。甚至能夠在不改變原有網站的架構上,經過在前端引入Nginx作負載均衡來提高網站的訪問速度。
-------------------------------------------------------下面對Nginx的一些特殊設置作一說明-------------------------------------------------------
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
好比訪問https://www.wangshibo.com/HouseGroup/index.html,跳轉到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僞靜態設置--------- 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跳轉規則,有如下四種flag標記:
last 基本上都用這個Flag,表示rewrite。
break 停止Rewirte,不在繼續匹配。就是說本條規則匹配完成後,終止匹配,再也不匹配後面的規則。
redirect 返回臨時重定向的HTTP狀態302;瀏覽器地址會顯示跳轉後的URL地址。
permanent 返回永久重定向的HTTP狀態301;瀏覽器地址會顯示跳轉後的URL地址。
1)下面是能夠用來判斷的表達式:
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執行
先來看幾個小例子說明
例以下面這段設定nginx將某個目錄下面的文件重定向到另外一個目錄,$2對應第二個括號(.*)中對應的字符串: location /download/ { rewrite ^(/download/.*)/m/(.*)\..*$ $1/nginx-rewrite/$2.gz break; } ----------------------------------------------------------------------------------- 例如當用戶輸入 www.a.com.cn 自動跳轉到www.a.com 這個域名: rewrite ^/(.*)$ http://www.a.com/$1 permanent; ----------------------------------------------------------------------------------- 例以下面設定nginx在用戶使用ie的使用重定向到/nginx-ie目錄下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; } ----------------------------------------------------------------------------------- 例如當用戶訪問testxqsjapi.xqshijie.com域名時跳轉到本機的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 實現二級域名跳轉 當訪問http://abc.wangshibo.com跳轉到http://www.wangshibo.com/wangshibo/abc/ 方法一:這種方法瀏覽器地址會變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; } } 方法二:當訪問http://abc.wangshibo.com/*跳轉到http://www.wangshibo.com/wangshibo/abc/* server { listen 80; server_name *.wangshibo.com; root /usr/local/www; #這是裏能夠加多個目錄,若是不加目錄,會沒法訪問到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; }
再接着看下面的實例說明
#直接匹配網站根,經過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。 #這裏是直接轉發給後端應用服務器了,也能夠是一個靜態首頁 # 第一個必選規則 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/ }
2)實例說明
1)訪問A站跳轉(重定向)到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;
}
================================================================================
訪問一個主域名,自動添加www前綴。好比訪問http://kevin.com自動跳轉http://www.kevin.com
1) 首先要保證不加www和加www的域名都要解析出來。 在DNS裏添加kevin.com和www.kevin.com的解析,好比解析到111.110.11.18 @ IN A 111.110.11.18 www IN A 111.110.11.18 解釋: A記錄解析kevin.com到111.110.11.18地址上,前面加@或者留空(留空默認就是@) A記錄解析www.kevin.com到111.110.11.18地址上,前面加www 2)nginx配置不加www自動跳轉到www的域名訪問(80或443都同樣),有下面兩種方法實現: 方法一: 在conf/vhost/kevin.conf文件中配置: server { listen 80; server_name www.kevin.com kevin.com; index index.jsp index.html index.php index.htm; root /var/www/html; access_log /data/nginx/logs/www.kevin.com-access.log main; error_log /data/nginx/logs/www.kevin.com-error.log; if ($host = "kevin.com") { rewrite ^/(.*)$ http://www.kevin.com permanent; } } 方法二(官方推薦這一種nginx的301跳轉方法) 在conf/vhost/kevin.conf文件中配置: server { listen 80; server_name kevin.com; return 301 http://www.kevin.com$request_uri; } server { listen 80; server_name www.kevin.com; index index.jsp index.html index.php index.htm; root /var/www/html; access_log /data/nginx/logs/www.kevin.com-access.log main; error_log /data/nginx/logs/www.kevin.com-error.log; }
2)多域名綁定一個目錄,而且所有301跳轉到其中一個域名(注意:多域名都要解析到本機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的時候都會自動跳轉到
http://www.wangshibo.com,而且瀏覽器地址會顯示跳轉後的URL地址。
若是是上面多域名訪問後都重定向跳轉到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;
}
以下配置:多域名中的某個域名訪問時發生跳轉,其餘域名訪問時不跳轉
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)將多級目錄下的文件轉成一個文件,加強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就會跳轉到http://www.wangshibo.com/wang/123/456/wangshow_789.html
4)訪問的目標文件和目錄資源不存在的時候重定向跳轉
以下配置,當訪問http://www.wangshibo.com/後面的訪問資源(文件或目錄)不存在時,通通跳轉到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)將站點根目錄下某個目錄指向二級目錄
例如將/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的時候就會跳轉到http://www.wangshibo.com/ops/huanqiu/
注意:上面的配置中的last修改成permanent或redirect均可以
以上的配置也適用於:(前提是這些目錄要真是存在於站點目錄/var/www/html/中,而且權限要正確)
將/wangshibopc/指向/ops/wangshibo/
將/guohuihuipc/指向/ops/guohuihui/
將/hahapc/指向/ops/haha/
......
6)其餘的rewrite跳轉規則的例子:
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; #本機站點目錄下並不須要真實存在abc這個目錄,對虛擬目錄的訪問都重寫到http://www.huanqiu.com } #即訪問http://www.wangshibo.com/abc,跳轉到http://www.huanqiu.com location /text { rewrite / http://china.huanqiu.com break; #本機站點目錄下須要真實存在text目錄,對其的訪問都重寫到http://china.huanqiu.com } #即訪問http://www.wangshibo.com/text,跳轉到http://china.huanqiu.com }
下面一例:訪問http://www.wangshibo.com/g/4HG45SkZ 實際訪問地址跳轉爲 http://110.10.88.99:8081/qun/share/view?code=4HG45SkZ
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表示第一個變量,即前面rewrite後第一個()內設置的變量
$2表示第二個變量,即前面rewrite後第二個()內設置的變量
再看一例:
訪問http://www.wangshibo.com/thumb/transcode 實際訪問地址爲 http://120.170.190.99:28080/transcode/thumb/transcode
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; } }
----------------------------再看一個訪問nginx跳轉後的url不變的例子--------------------------------------
須要特別注意的是: proxy_pass 反向代理,能夠實現只改變跳轉後的內容,而跳轉後的原url保持不變! rewrite 重寫跳轉後會進行重定向,很難實現跳轉後的原url不變的需求。 看看以前踩過的坑; 要求訪問http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,內容跳轉到http://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken,可是跳轉後的url保持不變! 這是根據path路徑進行反向代理的配置,即要求訪問http://wx2.xqshijie.com/apiwx2/$1 跳轉到http://m.xqshijie.com/$1,跳轉後的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; } } 根據上面配置後,就能夠實現訪問http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,實際顯示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的內容,可是跳轉後的原來的url不變! 若是採用rewrite重寫規則,即將: 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,實際顯示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的內容,可是跳轉後的url已經變了! 上面碰到過的坑: 因爲訪問http://m.xqshijie.com就會自動跳轉到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,實際顯示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的內容,可是跳轉後的原來的url已經變了! 緣由是由於這裏通過了兩次跳轉,即rewrite->http->https,因此跳轉後的url變了。 解決辦法:就是直接rewrite跳轉到https,即proxy_pass https://m.xqshijie.com/;
----------------------------下面的跳轉規則表示---------------------------------------
訪問http://www.wangshibo.com/wangshibo/ops就會跳轉到http://www.wangshibo.com/ops/wangshibo
訪問http://www.wangshibo.com/wangshibo/beijing就會跳轉到http://www.wangshibo.com/beijing/wangshibo
......
即由"wangshibo/變量"-->"變量/wangshibo"
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 跳轉到 http://www.wangshibo.com/web/ops/web/
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 實際訪問地址跳轉爲 http://www.hehe.com/qun/share/view?code=123
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; }
其餘配置實例
若是nginx在用戶使用IE瀏覽器訪問狀況下,則重定向到/nginx-ie目錄下 配置以下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; } 多目錄轉成參數 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; } 目錄自動加"/",前提是訪問目錄存在 配置以下: if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; } 三級域名跳轉 配置以下: if ($http_host ~* 「^(.*)\.i\.beijing\.com$」) { rewrite ^(.*) http://www.wangshibo.com$1/; break; } 針對站點根目錄下的某個子目錄做鏡向 配置以下:就會把http://www.huanqiu.com的內容(即首頁)鏡像到/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; } 域名鏡像(其實就是域名跳轉) 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;
目錄對換:/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的目錄對換的跳轉測試
如上配置後,那麼:
訪問http://www.wangshibo.com/?id=567567567567567 的結果就是http://www.wangshibo.com/的結果
訪問http://www.wangshibo.com/ops/?id=wangshibo 的結果就是http://www.wangshibo.com/ops的結果
訪問http://www.wangshibo.com/wang/?id=123111 的結果就是http://www.wangshibo.com/wang的結果
.......
2.反向代理(proxy_pass)
簡單測試nginx反向代理和負載均衡功能的操做記錄(1)-----http代理
簡單測試nginx反向代理和負載均衡功能的操做記錄(2)-----https代理
3.緩存設置
nginx反向代理+緩存開啓+url重寫+負載均衡(帶健康探測)的部署記錄
nginx緩存配置的操做記錄梳理
4.防盜鏈。關於Nginx防盜鏈具體設置,可參考:Nginx中防盜鏈(下載防盜鏈和圖片防盜鏈)的操做記錄
location ~* \.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}
下面設置文件反盜鏈並設置過時時間:
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狀態碼,默認爲403,方便找出正確的盜鏈的請求
「rewrite ^/ http://img.wangshibo.net/leech.gif;」顯示一張防盜鏈圖片
「access_log off;」不記錄訪問日誌,減輕壓力
「expires 3d」全部文件3天的瀏覽器緩存
5.根據文件類型設置過時時間
1)expires起到控制頁面緩存的做用,合理的配置expires能夠減小不少服務器的請求;
2)對於站點中不常常修改的靜態內容(如圖片,JS,CSS),能夠在服務器中設置expires過時時間,控制瀏覽器緩存,達到有效減少帶寬流量,下降服務器壓力的目的。
3)Expires是Web服務器響應消息頭字段,在響應http請求時告訴瀏覽器在過時時間前瀏覽器能夠直接從瀏覽器緩存取數據,而無需再次請求。
要配置expires,能夠在http段中或者server段中或者location段中加入;
以下:控制圖片等過時時間爲30天,若是圖片文件不怎麼更新,過時能夠設大一點;若是頻繁更新,則能夠設置得小一點,具體視狀況而定
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 應答中的「 Expires 」和「 Cache-Control 」的頭標(起到控制頁面緩存的做用)
語法:expires [time|epoch|max|off]
默認值:off
expires指令控制HTTP應答中的「Expires」和「Cache-Control」Header頭部信息,啓動控制頁面緩存的做用
time:可使用正數或負數。「Expires」頭標的值將經過當前系統時間加上設定time值來設定。
time值還控制"Cache-Control"的值:
負數表示no-cache
正數或零表示max-age=time
epoch:指定「Expires」的值爲 1 January,1970,00:00:01 GMT
max:指定「Expires」的值爲31 December2037 23:59:59GMT,"Cache-Control"的值爲10年。(即設置過時時間最最長)
-1:指定「Expires」的值爲當前服務器時間-1s,即永遠過時。
off:不修改「Expires」和"Cache-Control"的值
expires使用了特定的時間,而且要求服務器和客戶端的是中嚴格同步。
而Cache-Control是用max-age指令指定組件被緩存多久。
對於不支持http1.1的瀏覽器,仍是須要expires來控制。因此最好能指定兩個響應頭。但HTTP規範規定max-age指令將重寫expires頭。
如何檢測nginx中設置的expires網頁過時時間是否生效?
方法:
打開webkaka的網站速度診斷工具(http://pagespeed.webkaka.com/),輸入你的網頁地址,檢測後,當即能夠看到設置是否生效了。以下圖所示:
上圖能夠看到,被檢測網頁的js文件過時時間爲1天(12h)。
6.禁止訪問某個文件或目錄
1)禁止訪問以txt或doc結尾的文件
location ~* \.(txt|doc)${
root /data/www/wwwroot/linuxtone/test;
deny all;
}
2)nginx禁止訪問全部.開頭的隱藏文件設置
location ~* /.* {
deny all;
}
3)nginx禁止訪問目錄
location ^~ /path {
deny all;
}
4)禁止訪問擴展名爲bat的文件
location ~* /.bat {
deny all;
}
5)禁止訪問configs目錄,以及其下全部子目錄或文件
location ^~ /configs/ {
deny all;
}
注意上述configs後面的斜槓不能少,不然全部以configs開頭的目錄或文件都將禁止訪問。
6)禁止訪問多個目錄
location ~ ^/(cron|templates)/ {
deny all;
break;
}
7)禁止訪問以/data開頭的文件
location ~ ^/data {
deny all;
}
8)禁止訪問以.sh,.flv,.mp3爲文件後綴名的文件
location ~ .*\.(sh|flv|mp3)$ {
return 403;
}
9)或者以=符號形式
location = /config/ {
return 404;
}
location =/config.ini{
return 404;
}
10)禁止htaccess
location ~/\.ht {
deny all;
}
return指令
語法:returncode ;
使用環境:server,location,if;
該指令用於結束規則的執行並返回狀態碼給客戶端。
例如:訪問的URL以".sh"或".bash"結尾,則返回403狀態碼
location ~ .*\.(sh|bash)?$ {
return 403;
}
7.禁止IP訪問 只容許域名訪問
當別人經過ip或者未知域名訪問你的網站的時候,你但願禁止顯示任何有效內容,能夠給他返回500.
目前國內不少機房都要求網站主關閉空主機頭,防止未備案的域名指向過來形成麻煩。
爲了不網站遭受惡意IP攻擊,須要禁止IP訪問,只能使用域名訪問站點!
listen行加上default(或default_server)參數,表示這個是默認虛擬主機。
因此,禁止ip訪問,只能使用域名訪問的正確配置是:
server {
listen 80 default;
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配置中指定域名的同時,也指明瞭ip訪問,好比server_name 103.110.186.17 web01.wangshibo.cn
那麼儘管上面已經作了返回500設置,也禁止不了ip訪問!也就是說,只要server_name一行指明瞭ip訪問,那麼就禁止不了了。
以上設置,能夠將ip訪問禁用,這樣的話,使用ip訪問的流量就會丟失。
若是想把這部分流量收集起來,導入到本身的網站,只要作如下跳轉設置就能夠:
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;
}
下面列出其餘的一些細節致使的不一樣效果:
1)將ip和域名訪問通通禁止,返回403(或者配置return 500)錯誤頁
server {
listen 80 default;
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訪問配置中的站點(/var/www/html)
不能使用ip,即http://103.110.186.17訪問配置中的站點。可是可使用ip方式訪問nginx默認的根目錄下的內容(好比/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均可以訪問配置中的站點。(使用ip訪問只限於只有一個vhost虛擬主機配置的狀況,若是是多個,那麼指明ip訪問就會混淆)
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)下面兩個的配置後,都能使用域名或ip訪問配置中的站點。
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;
}
======================================================================
nginx配置只能經過域名禁止ip訪問
爲何要禁止ip訪問頁面呢,這樣作是爲了不其餘人把未備案的域名解析到本身的服務器IP,而致使服務器被斷網, 能夠經過禁止使用ip訪問的方法,防止此類事情的發生。 Nginx的默認虛擬主機在用戶經過IP訪問,或者經過未設置的域名訪問(好比有人把他本身的域名指向了你的ip)的時候 生效最關鍵的一點是,在server的設置裏面添加這一行: listen 80 default; 後面的default參數表示這個是默認虛擬主機。這個設置很是有用。 好比別人經過ip或者未知域名訪問你的網站的時候,你但願禁止顯示任何有效內容,能夠給他返回500。 網站主關閉空主機頭,防止未備案的域名指向過來形成麻煩。就能夠這樣設置: server { listen 80 default; return 500; } 也能夠把這些流量收集起來,導入到本身的網站,只要作如下跳轉設置就能夠: server { listen 80 default; rewrite ^(.*) http://www.xxx.com permanent; } -----------------特別注意------------------- 按照如上設置後,確實不能經過IP訪問服務器了,可是在應該用中出現當server_name後跟多個域名時, 其中一個域名怎麼都沒法訪問: 設置以下: 沒更改以前,經過server_name 中的www.xxx.com kevin.com都可訪問服務器,加入禁止IP訪問的設置後,經過kevin.com沒法訪問服務器了,www.xxx.com能夠訪問 用 nginx -t 檢測配置文件會提示warning: 最後經過在listen 80 default;後再加server_name _;解決,形式以下: #禁止IP訪問(若是vhosts下面有不少域名的conf配置,那麼只須要建立建立一個文件,好比deny.ip.conf,輸入下面五行內容,這樣就全局禁止了ip訪問,只能使用域名訪問了!) server{ listen 80 default; //若是是禁止ip的8080端口訪問,則將此處的80修改成8080 server_name _; return 500; } 或者 server { listen 80 dufault; server_name _; rewrite ^(.*) http://www.xxx.com permanent; } 這樣,經過xxx.com就能訪問服務器了,問題解決了。 ===================================================================== 也可使用以下設置:即在server段裏插入以下內容便可 if ($host != 'www.kevin.com' ) { return 403; } =====================================================================
8.流量限制
對於提供下載的網站,確定是要進行流量控制的,例如BBS、視頻服務,仍是其它專門提供下載的網站。在nginx中咱們徹底能夠作到限流,由Nginx模塊中的Core模塊提供了limit_rate、limit_rate_after命令,咱們只須要調用命令實現流量限制就行。
實現流量限制由兩個指令limit_rate和limit_rate_after共同完成:
limit_rate
語法: limit_rate rate;
默認值: limit_rate 0;
做用域: http, server, location, location中的if字段
命令概述:限制向客戶端傳送響應的速率限制。參數 rate 的單位是字節/秒,設置爲 0 將關閉限速。 nginx 按鏈接限速,須要明白的一點是該限制只是針對一個鏈接的設定,因此若是某個客戶端同時開啓了兩個鏈接,那麼客戶端的總體速率是這條指令設置值的2倍。
limit_rate_after
語法: limit_rate_after size;
默認值: limit_rate_after 0;
做用域:http, server, location,location中的if字段
設置不限速傳輸的響應大小。當傳輸量大於此值時,超出部分將限速傳送。
示例說明:
server {
listen 80;
server_name ops.wangshibo.com;
location /ops/{
root /home/www/html;
limit_rate_after 5m;
limit_rate 20k;
}
}
測試:
[root@test-huanqiu ~]# wget http://ops.wangshibo.com/ops/seven.mp4
修改配置以前,速率沒有限制:
修改配置以後,可見因爲傳輸量大於5m,超出部分的傳輸速率已經被限制在20k/s:
能夠發現配置以後,剛開始的時候傳輸速度很高,由於,傳輸量大於設定值的部分纔會受到限制。這就說明,咱們兩個命令都發揮了做用!
9.併發鏈接數限制
這個配置是基於ngx_http_limit_zone_module模塊的,要簡單完成併發限制,咱們要涉及到limit_conn_zone和limit_conn 這兩個指令:
limit_conn_zone
語法:limit_conn_zone zone_name $variable the_size
默認值:no
做用域:http
本指令定義了一個數據區,裏面記錄會話狀態信息。 variable 定義判斷會話的變量;the_size 定義記錄區的總容量。
limit_conn
語法:limit_conn zone_name the_size
默認值:no
做用域:http, server, location
指定一個會話最大的併發鏈接數。 當超過指定的最發併發鏈接數時,服務器將返回 "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)定義一個叫「one」的記錄區,總容量爲 10M,以變量$binary_remote_addr做爲會話的判斷基準(即一個地址一個會話)。
限制/ops/目錄下,一個會話只能進行一個鏈接;簡單來講,就是限制/ops/目錄下,一個IP只能發起一個鏈接,多過一個,一概報錯503。
2)這裏使用的是$binary_remote_addr而不是 $remote_addr。$remote_addr的長度爲7至15 bytes,會話信息的長度爲32或64bytes;而 $binary_remote_addr的長度爲4bytes,會話信息的長度爲32bytes;$binary_remote_addr是限制同一客戶端ip地址;當 zone 的大小爲 1M 的時候,大約能夠記錄 32000 個會話信息(一個會話佔用 32 bytes)。
下面分享一個限制流量和併發送的配置:
現象描述:
中間一段時間,網站訪問有點慢,初步懷疑是機房交換機問題(以前出現過網站訪問很慢,熱插拔網卡/重啓網卡就行了)
最後查看,發現機房流量很大!主要是論壇流量大,主站流量很小,應該是論壇人數訪問一多,就把帶寬佔滿了。
解決辦法:
在論壇服務器上修改:
1)首先限制併發數
[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
上面將每一個用戶限制在每秒6個請求,但效果不明顯。
2)設置nginx的流量請求
[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; //這裏調用上面的perip,須要寫在server裏面;即每一個ip最多有10個併發鏈接
limit_rate 10k; //限制每一個鏈接的帶寬,能夠單獨寫這條,與鏈接數無關;
}
}
[root@server_web ~]# /usr/local/nginx/sbin/nginx -s reload
======================Nginx下的限流配置=====================
limit_req_zone 用來限制單位時間內的請求數,即速率限制,採用的漏桶算法 "leaky bucket" #點擊前面超連接可查看對應模塊官方介紹
limit_req_conn 用來限制同一時間鏈接數,即併發限制
其中limit_req_conn模塊能夠根據源IP限制單用戶併發訪問的鏈接數或鏈接到該服務的總併發鏈接數 什麼是漏桶算法? 咱們假設系統是一個漏桶,當請求到達時,就是往漏桶裏"加水",而當請求被處理掉,就是水從漏桶的底部漏出。水漏出的速度是固定的,當"加水"太快, 桶就會溢出,也就是"拒絕請求"。從而使得桶裏的水的體積不可能超出桶的容量。主要目的是控制數據注入到網絡的速率,平滑網絡上的突發流量。漏桶算 法提供了一種機制,經過它,突發流量能夠被整形以便爲網絡提供一個穩定的流量。 示例一: http { limit_conn_log_level error; limit_conn_status 503; limit_conn_zone $binary_remote_addr zone=one:10m; limit_conn_zone $server_name zone=perserver:10m; limit_req_zone $binary_remote_addr zone=allips:100m rate=10r/s; #其中$binary_remote_addr有時須要根據本身已有的log_format變量配置進行替換 server { ........ limit_conn one 100; limit_conn perserver 1000; limit_req zone=allips burst=5 nodelay; ....... } } 參數解釋: Zone=one或allips 表示設置了名爲"one"或"allips"的存儲區,大小爲10兆字節 rate=10r/s 意思是容許1秒鐘不超過10個請求 burst=5 表示最大延遲請求數量不大於5。 若是太過多的請求被限制延遲是不須要的 ,這時須要使用nodelay參數,服務器會馬上返回503狀態碼。 limit_conn one 100表示最大併發鏈接數100 limit_conn perserver 1000表示該服務提供的總鏈接數不得超過1000,超過請求的會被拒絕 示例二: http { limit_req_zone $binary_remote_addr zone=one:100m rate=10r/m; server { ....... limit_req zone=one burst=1 nodelay; ...... } } 解釋: rate=10r/m 意思是容許1秒鐘不超過1個請求,最大延遲請求數量不大於5。 若是請求不須要被延遲,添加nodelay參數,服務器會馬上返回503狀態碼。若是沒有該字段會形成大量的tcp鏈接請求等待。 http{ limit_zone one $binary_remote_addr 10m; server { ...... limit_conn one 1; ...... } } 這裏的 one 是聲明一個 limit_zone 的名字,$binary_remote_addr是替代 $remore_addr 的變量,10m是會話狀態儲存的空間。 limit_conn one 1 ,限制客戶端併發鏈接數量爲1,allow only one connection per an IP address at a time(每次)。 按照字面的理解,lit_req_zone的功能是經過漏桶原理來限制用戶的鏈接頻率,(這個模塊容許你去限制單個地址指定會話或特殊須要的請求數 ) 而 limit_zone 功能是限制一個客戶端的併發鏈接數。(這個模塊能夠限制單個地址的指定會話或者特殊狀況的併發鏈接數) 一個是限制併發鏈接一個是限制鏈接頻率,表面上彷佛看不出來有什麼區別,那就看看實際的效果吧~~~ 在個人測試機上面加上這兩個參數下面是個人部分配置文件 http{ limit_zone one $binary_remote_addr 10m; #limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s; server { ...... limit_conn one 1; #limit_req zone=req_one burst=120; ...... } } 解釋一下 limit_zone one $binary_remote_addr 10m; 這裏的 one 是聲明一個 limit_zone 的名字,$binary_remote_addr是替代 $remore_addr 的變量,10m是會話狀態儲存的空間 limit_conn one 1 ,限制客戶端併發鏈接數量爲1 ============================================================================ limit_zone兩種工做狀況 a)limit_reqzone=one burst=10 ; 默認狀況下是這樣配置的,這樣每一個請求就會有一個delay時間, limit_req_zone$binary_remote_addr zone=one:100m rate=10r/m; 就是每分鐘有10個令牌供用戶使用,按照a的配置狀況,就會有一個delay,每一個請求時間就是60/10,那每一個請求時間就是6s。 b)limit_reqzone=one burst=10 nodelay; - 添加nodelay配置,這樣就是根據你的網絡情況訪問,一分鐘訪問夠10次後,服務器直接返回503。 - limit_req_zone$binary_remote_addr zone=one:100m rate=10r/m; 就是每分鐘有10個令牌供用戶使用,按照b的配置狀況,就會根據網絡狀況訪問url,若是一分鐘超過10個令牌,服務器返回503, 等待下一個一分鐘領取訪問令牌。 rate=10r/m 的意思是每一個地址每分鐘只能請求10次,也就是說根據漏桶原理burst=1 一共有1塊令牌,而且每分鐘只新增10塊 令牌,1塊令牌發完後多出來的那些請求就會返回503。 加上nodelay以後超過 burst大小的請求就會直接返回503,若是沒有該字段會形成大量的tcp鏈接請求等待。 例如: http{ ... #定義一個名爲allips的limit_req_zone用來存儲session,大小是10M內存, #以$binary_remote_addr 爲key,限制平均每秒的請求爲20個, #1M能存儲16000個狀態,rete的值必須爲整數, #若是限制兩秒鐘一個請求,能夠設置成30r/m limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s; ... server{ ... location { ... #限制每ip每秒不超過20個請求,漏桶數burst爲5 #brust的意思就是,若是第1秒、2,3,4秒請求爲19個, #第5秒的請求爲25個是被容許的。 #可是若是你第1秒就25個請求,第2秒超過20的請求返回503錯誤。 #nodelay,若是不設置該選項,嚴格使用平均速率限制請求數, #第1秒25個請求時,5個請求放到第2秒執行, #設置nodelay,25個請求將在第1秒執行。 limit_req zone=allips burst=5 nodelay; ... } ... } ... } 限制下載速度: location /download { limit_rate 128k; } #若是想設置用戶下載文件的前10m大小時不限速,大於10m後再以128kb/s限速能夠增長如下配內容,修改nginx.conf文件 location /download { limit_rate_after 10m; limit_rate 128k; } ==================================================================== nginx流量限制的使用場景 你們都知道服務器資源有限的,可是客戶端來的請求是無限的(不排除惡意攻擊), 爲了保證大部分的請求可以正常響應,不得不放棄一些客戶端來的請求, 因此咱們會採用Nginx的限流操做, 這種操做能夠很大程度上緩解服務器的壓力, 使其餘正常的請求可以獲得正常響應。 如何使用Nginx實現基本的限流,好比單個IP限制每秒訪問50次。經過Nginx限流模塊,咱們能夠設置一旦併發鏈接數超過咱們的設置,將返回503錯誤給客戶端。 這樣能夠很是有效的防止CC攻擊。再配合 iptables防火牆,基本上CC攻擊就能夠無視了。 配置實例: #統一在http域中進行配置 #限制請求 limit_req_zone $binary_remote_addr $uri zone=api_read:20m rate=50r/s; #按ip配置一個鏈接 zone limit_conn_zone $binary_remote_addr zone=perip_conn:10m; #按server配置一個鏈接 zone limit_conn_zone $server_name zone=perserver_conn:100m; server { listen 80; server_name report.52itstyle.com; index login.jsp; location / { #請求限流排隊經過 burst默認是0 limit_req zone=api_read burst=5; #鏈接數限制,每一個IP併發請求爲2 limit_conn perip_conn 2; #服務所限制的鏈接數(即限制了該server併發鏈接數量) limit_conn perserver_conn 1000; #鏈接限速 limit_rate 100k; proxy_pass http://report; } } upstream report { fair; server 192.168.10.12:8882 weight=1 max_fails=2 fail_timeout=30s; server 192.168.10.12:8881 weight=1 max_fails=2 fail_timeout=30s; } 配置503錯誤 默認狀況,超出限制額度,將會報503錯誤,提示: 503 Service Temporarily Unavailable The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. Sorry for the inconvenience. Please report this message and include the following information to us. Thank you very much! 這樣顯示沒毛病,可是不夠友好,這裏咱們自定義503錯誤。 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; #自定義50X錯誤 } 配置說明 limit_conn_zone 是針對每一個IP定義一個存儲session狀態的容器。這個示例中定義了一個100m的容器,按照32bytes/session,能夠處理3200000個session。 limit_rate 300k; 對每一個鏈接限速300k. 注意,這裏是對鏈接限速,而不是對IP限速。若是一個IP容許兩個併發鏈接,那麼這個IP就是限速limit_rate×2。 burst=5; 這至關於在檢查站req旁邊放5個座位。若是某個請求當時超過速度限制被攔了,請他在空座位上坐着,等排隊,若是檢查站空了,就能夠經過。 若是連座位都坐滿了,那就抱歉了,請求直接退回,客戶端獲得一個服務器忙的響應。因此說burst跟request_rate一點關係都沒有,設成10000, 就是1萬個請求能夠等着排隊,而檢查站仍是1秒鐘放行5個請求(龜速)。並且也不能一直排隊,因此nginx還設了超時,排隊超過必定時間, 也是直接退回,返回服務器忙的響應。 以上配置Nginx須要配置如下模塊: ngx_http_limit_conn_module (static) ngx_http_limit_req_module (static) 執行命令"nginx -V"就能夠檢查到是否有安裝。 =================================================================== 電商平臺營銷時候,常常會碰到的大流量問題,除了作流量分流處理,可能還要作用戶黑白名單、信譽分析,進而根據用戶ip信譽權重作相應的流量攔截、限制流量。 Nginx自身有的請求限制模塊ngx_http_limit_req_module、流量限制模塊ngx_stream_limit_conn_module基於令牌桶算法,能夠方便的控制令牌速率,自定義 調節限流,實現基本的限流控制。 對於提供下載的網站,確定是要進行流量控制的,例如軟件下載站、視頻服務等。它也能夠減小一些爬蟲程序或者DDOS的攻擊。 limit_zone指令能夠用limit_conn_zone替換 如何Nginx限制同一個ip的鏈接數,限制併發數目? 限流 1) 添加limit_zone和limit_req_zone 這個變量只能在http區域使用 : http { limit_zone one $binary_remote_addr 20m; limit_req_zone $binary_remote_addr zone=req_one:20m rate=12r/s; ...... } 2) 添加limit_conn 和limit_req 這個變量能夠在http, server, location使用。若是限制nginx上的全部服務,就添加到http裏面;若是限制部分服務,就添加到相應的server或者location裏。 http { limit_zone one $binary_remote_addr 20m; limit_req_zone $binary_remote_addr zone=req_one:20m rate=12r/s; limit_conn one 10; limit_req zone=req_one burst=120; ...... } 參數詳解(數值按具體須要和服務器承載能力設置): limit_zone,是針對每一個變量(這裏指IP,即$binary_remote_addr)定義一個存儲session狀態的容器。這個示例中定義了一個20m的容器,按照32bytes/session,能夠處理640000個session。 limit_req_zone 與limit_zone相似。rate是請求頻率. 每秒容許12個請求。 limit_conn one 10 : 表示一個IP能發起10個併發鏈接數 limit_req: 與limit_req_zone對應。burst表示緩存住的請求數。 配置範例: http { limit_zone one $binary_remote_addr 20m; limit_req_zone $binary_remote_addr zone=req_one:20m rate=12r/s; limit_conn one 10; limit_req zone=req_one burst=120; server { listen 80; server_name status.test.kevin.com ; location / { stub_status on; access_log off; } } } ++++++++++++++++++++++++++++++++++++++++++++++++++++++ nginx白名單設置 以上配置會對全部的ip都進行限制,有些時候咱們不但願對搜索引擎的蜘蛛或者某些本身的代理機過來的請求進行限制, 對於特定的白名單ip咱們能夠藉助geo指令實現。 先在nginx的請求日誌進行統計,查看那個ip的訪問量比較大,運行: # cat access.log | grep "03/Jun" |awk '{print $1}'|sort |uniq -c|sort -nrk 1|head -n 10 #列出訪問日誌裏面在6月3號這天前10個訪問量最大的ip. 接下來就能夠對這些IP進行分析了。看哪些須要進行白名單設置。 http{ geo $limited { # the variable created is $limited default 1; 127.0.0.1/32 0; 10.12.212.63 0; } map $limited $limit { 1 $binary_remote_addr; 0 ""; } limit_zone one $binary_remote_addr 20m; limit_req_zone $limit zone=req_one:20m rate=20r/s; limit_conn one 10; limit_req zone=req_one burst=120; } 上面兩個須要用到map和geo模塊,這是nginx自帶的模塊,有的運維喜歡把他們關閉,本身./sbin/nginx -V 留意一下。 把配置的--whithout-XXX-module 去掉從新編譯一下就能夠了。 上面這段配置的意思是: a)geo指令定義了一個白名單limited變量,默認值爲1,若是客戶端ip在上面的範圍內,limited變量,默認值爲1,若是客戶端ip在上面的範圍內, limited的值爲0 b)使用map指令映射搜索引擎客戶端的ip爲空串,若是不是搜索引擎就顯示自己真實的ip,這樣搜索引擎ip就不能存到limit_req_zone內存session中, 因此不會限制搜索引擎的ip訪問 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 獲取客戶端的真實IP? 順帶一提,爲了獲取客戶端的真實IP。該模塊須要安裝read_ip模塊,運維應該默認有安裝。沒有的話也可自行安裝: 配置方式至關簡單,從新編譯Nginx 加上 --with-http_realip_module 參數,如: # ./configure --prefix=/opt/nginx --with-http_stub_status_module --with-pcre=../pcre-6.6 --with-http_realip_module # make # make install 在server中增長: set_real_ip_from 192.168.1.0/24; set_real_ip_from 192.168.2.1; real_ip_header [X-Real-IP|X-Forwarded-For]; 須要說明的地方就是設置IP源的時候能夠設置單個IP,也能夠設置IP段,另外是使用X-Real-IP仍是X-Forwarded-For,取決於前面的服務器有哪一個頭。 set_real_ip_from 設置的IP端可讓運維查看日誌,看下你的請求是來自哪些ip段。 從新加載一下服務,差很少就OK了。 再查看日誌的話,應該能夠看到客戶端的真實IP了。 注意:若是未安裝該模塊的話你的獲取到的IP端多是來自前端代理(如squid)的IP,結果就是多個用戶被當成單個用戶對待,致使應用不能響應。 ------自測: 有條件的本身能夠用ab或者webben自測一下-------- 未安裝前壓測的話,由於有大量請求,因此access.log會有大量日誌,而error.log日誌沒有變化。 [root@kevin ~]# webbench -c 30 -t 30 http://test.kevin.com Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://test.kevin.com 30 clients, running 30 sec. Speed=193468 pages/min, 1254317 bytes/sec. Requests: 96734 susceed, 0 failed. 安裝後會發現不少超出的請求會返回503,因此access.log日誌變化不快,error.log有大量記錄,提示limit_reque緩住了多少請求。 kevin ~ webbench -c 30 -t 30 http://test.kevin.com Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://test.kevin.com 30 clients, running 30 sec. Speed=120 pages/min, 778 bytes/sec. Requests: 60 susceed, 0 failed.
10.nginx的訪問控制及DDOS預防
1)訪問控制配置
基於各類緣由,Ningx有時要進行訪問控制。
好比說,通常網站的後臺都不能讓外部訪問,因此要添加 IP 限制,一般只容許公司的IP訪問。
訪問控制就是指只有符合條件的IP才能訪問到這個網站的某個區域。
涉及模塊:ngx_http_access_module
模塊概述:容許限制某些 IP 地址的客戶端訪問。
對應指令:
allow
語法: allow address | CIDR | unix: | all;
默認值: —
做用域: http, server, location, limit_except
容許某個 IP 或者某個 IP 段訪問。若是指定 unix,那將容許 socket 的訪問。注意:unix 在 1.5.1 中新加入的功能,若是你的版本比這個低,請不要使用這個方法。
deny
語法: deny address | CIDR | unix: | all;
默認值: —
做用域: http, server, location, limit_except
禁止某個 IP 或者一個 IP 段訪問。若是指定 unix,那將禁止 socket 的訪問。注意:unix 在 1.5.1 中新加入的功能,若是你的版本比這個低,請不要使用這個方法。
示例說明:
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;
}
}
規則按照順序依次檢測,直到匹配到第一條規則。
在這個例子裏,只有 10.1.1.0/16 、192.168.1.0/24和103.10.67.56容許訪問,但 192.168.1.1 除外。
以下實例:
1)先是多域名綁定一個目錄後的301跳轉至同一個域名
2)針對網站訪問作來源ip白名單設置,並加上密碼。(即用戶認證配置)
[root@test-huanqiu vhosts]# cat test.conf
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
訪問站點http://www.wangshibo.com,效果以下:
ngx_http_access_module 配置容許的地址能訪問,禁止的地址被拒絕。這只是很簡單的訪問控制,而在規則不少的狀況下,使用 ngx_http_geo_module 模塊變量更合適。
這個模塊你們下來能夠了解 : ngx_http_geo_module
-------------------------------------------------------------------------------------------------------
上面也用到了nginx的用戶認證的配置,其中:
auth_basic 認證時的提示信息
auth_basic_user_file 認證時存放用戶名和密碼的文件
# htpasswd -c /usr/local/nginx/htpasswd wangshibo //第一次設置認證的用戶
# htpasswd /usr/local/nginx/htpasswd guohuihui //追加認證的用戶,後面再次追加認證用戶時,不要加-c參數,不然就會覆蓋以前添加的用戶!
下面順便看幾個認證部分的配置:
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預防配置
DDOS的特色是分佈式,針對帶寬和服務攻擊,也就是四層流量攻擊和七層應用攻擊,相應的防護瓶頸四層在帶寬,七層的多在架構的吞吐量。
對於七層的應用攻擊,仍是能夠作一些配置來防護的,使用nginx的http_limit_conn和http_limit_req模塊經過限制鏈接數和請求數能相對有效的防護。
其中:
ngx_http_limit_conn_module 能夠限制單個 IP 的鏈接數
ngx_http_limit_req_module 能夠限制單個 IP 每秒請求數
配置方法:
(1)限制每秒請求數,即ip訪問頻率限制
涉及模塊:ngx_http_limit_req_module
經過漏桶原理來限制單位時間內的請求數,一旦單位時間內請求數超過限制,就會返回 503 錯誤。
配置範例:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;
...
server {
...
location ~ \.php$ {
limit_req zone=one burst=5 nodelay;
}
}
}
配置說明(上一部分解釋過的就再也不解釋):
定義一個名爲one的limit_req_zone用來存儲session,大小是10M內存,
以$binary_remote_addr 爲key,限制平均每秒的請求爲20個,
1M能存儲16000個狀態,rete的值必須爲整數,
rate=20r/s表示限制頻率爲每秒20個請求;若是限制兩秒鐘一個請求,能夠設置成30r/m。
限制每ip每秒不超過20個請求,漏桶數burst爲5
brust的意思就是,若是第1秒、2,3,4秒請求爲19個,
第5秒的請求爲25個是被容許的。
可是若是你第1秒就25個請求,第2秒超過20的請求返回503錯誤。
nodelay,若是不設置該選項,嚴格使用平均速率限制請求數,
第1秒25個請求時,5個請求放到第2秒執行,
設置nodelay,25個請求將在第1秒執行。
(2)限制IP鏈接數(上面已經說明,這裏直接寫配置)
http {
limit_conn_zone $binary_remote_addr zone=addr:10m; //上面講過
...
server {
...
location /ops/ {
limit_conn addr 1;
}
}
}
總的來講:如何設置能限制某個IP某一時間段的訪問次數是一個讓人頭疼的問題,特別面對惡意的ddos攻擊的時候。其中CC攻擊(Challenge Collapsar)是DDOS(分佈式拒絕服務)的一種,也是一種常見的網站攻擊方法,攻擊者經過代理服務器或者肉雞向向受害主機不停地發大量數據包, 形成對方服務器資源耗盡,一直到宕機崩潰。
cc攻擊通常就是使用有限的ip數對服務器頻繁發送數據來達到攻擊的目的。
nginx能夠經過Http LimitReq Modul和Http LimitZone Module配置來限制ip在同一時間段的訪問次數來防cc攻擊。
1)Http LimitReq Modul用來限制連單位時間內鏈接數的模塊,使用limit_req_zone和limit_req指令配合使用來達到限制。一旦併發鏈接超過指定數量,就會返回503錯誤。
2)Http LimitConn Modul用來限制單個ip的併發鏈接數,使用limit_zone和limit_conn指令
配置示例:
Http LimitReq Modul限制某一段時間內同一ip訪問數
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 限制併發鏈接數實例
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)限速白名單設置(可參考:nginx利用geo模塊作限速白名單以及geo實現全局負載均衡的操做記錄)
http_limit_conn和 http_limit_req模塊限制了單IP單位時間內的鏈接和請求數,可是若是Nginx前面有lvs或者haproxy之類的負載均衡或者反向代理,nginx 獲取的都是來自負載均衡的鏈接或請求,這時不該該限制負載均衡的鏈接和請求,就須要 geo 和 map 模塊設置白名單:
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 模塊定義了一個默認值是 1 的變量 whiteiplist,當在 ip 在白名單中,變量 whiteiplist 的值爲 0,反之爲1.
對上面設置的邏輯關係解釋:
若是在白名單中--> whiteiplist=0 --> $limit="" --> 不會存儲到 10m 的會話狀態(one 或者 addr)中 --> 不受限制;
反之,不在白名單中 --> whiteiplist=1 --> $limit=二進制遠程地址 -->存儲進 10m 的會話狀態中 --> 受到限制。
(4)動手測試DDOS預防配置
下面來測一下上面說到的配置是否起到了做用。
安裝nginx+php環境
寫一個測試的PHP文件,修改nginx配置文件,使其能正常訪問。
在/home/shiyanlou目錄下寫一個test.php,內容以下:
[root@server_web1 ~]# vim /home/shiyanlou/test.php
<?php
phpinfo ();
?>
nginx 配置文件修改:
最後展現:
使ab命令進行測試,比較修改nginx配置文件先後(鏈接數和請求數分開測試)的測試結果。
修改以前:
測試結果爲:
對nginx配置作修改(添加http和php配置以下的紅線內容),重啓,而後再進行測試
測試結果爲:
11.訪問白名單
參考:nginx訪問白名單設置以及根據$remote_addr分發
12.nginx的上傳下載設置
參考:nginx限制上傳大小和超時時間設置說明/php限制上傳大小
13.nginx目錄瀏覽及其驗證功能
參考:nginx下目錄瀏覽及其驗證功能配置記錄
14.Nginx下禁止指定目錄運行php腳本文件
很是簡單,直接經過location條件匹配定位後進行權限禁止。 在server配置段中增長下面的的配置: 1)若是是單個目錄 location ~* ^/uploads/.*\.(php|php5)$ { deny all; } 2)若是是多個目錄 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下禁止指定目錄運行PHP腳本,在虛擬主機配置文件中增長php_flag engine off指令便可,配置以下 "/website/uploads"> Options FollowSymLinks AllowOverride None Order allow,deny Allow from all php_flag engine off
15.Nginx下開啓gzip壓縮功能,大幅提升頁面加載速度
若是發現如上配置後,訪問頁面時,gzip壓縮沒有生效。通常緣由就是該頁面的相應的gzip_type類型沒有加進去。 檢查一個頁面的gzip是否生效: [root@uatinner-lb01 ~]# curl -I -H "Accept-Encoding: gzip, deflate" "http://www.kevin.com/blog/plugins/bo-coolings/bo-coolings.css" HTTP/1.1 200 OK Date: Fri, 14 Sep 2018 09:10:38 GMT Content-Type: text/html Connection: keep-alive Set-Cookie: __cfduid=da2267d06a7d8364c8d4c9193627d56f91536916238; expires=Sat, 14-Sep-19 09:10:38 GMT; path=/; domain=.slyar.com; HttpOnly CF-Cache-Status: EXPIRED Expires: Tue, 19 Mar 2019 09:10:38 GMT Cache-Control: public, max-age=16070400 Vary: Accept-Encoding Server: cloudflare CF-RAY: 45a1b8bb26712132-LAX Content-Encoding: gzip 若是發現訪問如上的http://www.kevin.com/blog/plugins/bo-coolings/bo-coolings.css頁面時,gzip沒有生效。 就注意查看下上面結果中的Content-Type類型的內容(如上是text/html)是否加到了nginx.conf文件中gzip配置區域裏。若是沒有,就加上,並reload nginx服務便可!
16.Nginx使用非root用戶啓動
在linux系統裏, 監聽端口在1024如下的服務必須使用root用戶啓動, 1024以上端口的應用服務可使用非root用戶啓動. 好比, nginx默認端口是80, 必須使用root用戶啓動. 考慮到安全問題, 採用非root用戶啓動, 好比app用戶. [root@web ~]# cat /data/nginx/conf/nginx.conf user app; 而後切換到app用戶下啓動 [root@web ~]# su - app [app@web ~]$ /data/nginx/sbin/nginx 非root用戶在檢查nginx配置文件或啓動nginx的時候,會出現告警信息: nginx: [warn] the "app" directive makes sense only if the master process runs with super-user privileges, ignored in /data/nginx/conf/nginx.conf:2 這是由於: - 在非root帳戶下啓動時,nignx的master和worker進程的owner都將是這個帳戶(這裏是app用戶), - 在root帳戶下啓動時 nignx的master進程是的owner是rootworker的owner在conf已配置用戶的狀況下,owner是配置的用戶,不然將是nobody, 並且也可能致使nginx的一些文件的owner也是nobody 因此出現了上面那個warn告警信息, 能夠忽略, 不影響 [app@web ~]$ ps -ef|grep nginx app 8837 1 0 16:02 ? 00:00:00 nginx: master process /data/nginx/sbin/nginx app 8838 8837 0 16:02 ? 00:00:00 nginx: worker process app 8839 8837 0 16:02 ? 00:00:00 nginx: worker process app 8840 8837 0 16:02 ? 00:00:00 nginx: worker process app 8841 8837 0 16:02 ? 00:00:00 nginx: worker process app 8842 8837 0 16:02 ? 00:00:00 nginx: worker process app 8843 8837 0 16:02 ? 00:00:00 nginx: worker process app 8844 8837 0 16:02 ? 00:00:00 nginx: worker process app 8845 8837 0 16:02 ? 00:00:00 nginx: worker process app 8846 8837 0 16:02 ? 00:00:00 nginx: cache manager process
17. Nginx實現404錯誤頁面跳轉的幾種方法
Nginx做爲經常使用網站的web服務器, 出現404錯誤頁面的跳轉實現方式主要有如下幾種: 第一種狀況: Nginx本身的錯誤頁面 Nginx訪問一個靜態的html 頁面,當這個頁面沒有的時候,Nginx拋出404,那麼如何返回給客戶端404呢? 看下面的配置,這種狀況下不須要修改任何參數,就能實現這個功能。 [root@localhost ~]# cat /data/nginx/conf/nginx.conf ......... http { proxy_intercept_errors on; //若是nginx不作代理, 不代理到後面的tomcat服務器, 只是本身的靜態頁訪問, 則這一行加不加均可以實現; [root@localhost ~]# cat /data/nginx/conf/test.conf server { listen 80; server_name localhost; access_log /data/nginx/logs/access.log main; error_log /data/nginx/logs/error.log; location / { root /data/web; index index.php index.html index.htm; } #定義錯誤頁面碼,若是出現相應的錯誤頁面碼,轉發到那裏。 error_page 404 403 500 502 503 504 /404.html; #承接上面的location。 location = /404.html { #放錯誤頁面的目錄路徑。 root /data/web; } } ------------------------------------------------------------------------------------------ 須要注意: 若是是跳轉到其餘url, 則配置改成: #定義錯誤頁面碼,若是出現相應的錯誤頁面碼,轉發到那裏。 error_page 404 403 500 504 http://www.haha.com; ------------------------------------------------------------------------------------------ 須要注意: 或是能夠設置多種類型的錯誤頁面 # 這裏的錯誤碼能夠是多個 error_page 500 502 503 504 /50x.html; location = /50x.html { root /data/web; } error_page 404 /404.html; location = /404.html { root /data/web; } 而後在定義的/data/web目錄下編寫50x.html和404.html錯誤頁面內容 ----------------------------------------------------------------------------------------- 到定義的錯誤頁面存放目錄下編輯404錯誤頁面內容: [root@localhost vhosts]# ll /data/web/ total 8 -rw-r--r-- 1 root root 50 Dec 19 16:04 404.html -rw-r--r-- 1 root root 21 Dec 19 15:59 index.html [root@localhost vhosts]# cat /data/web/404.html Sorry, sir, this page does not exist! Excuse me ~ 重啓nginx服務 [root@localhost vhosts]# /data/nginx/sbin/nginx -t nginx: the configuration file /data/nginx/conf/nginx.conf syntax is ok nginx: configuration file /data/nginx/conf/nginx.conf test is successful [root@localhost vhosts]# /data/nginx/sbin/nginx -s reload 而後訪問nginx的地址, 當訪問一個錯誤頁面時, 就會出現定義的404錯誤頁面內容: "Sorry, sir, this page does not exist! Excuse me ~" ============================================ 第二種:反向代理的錯誤頁面 (nginx代理的後端是tomcat頁面, 使用proxy_intercept_errors on參數, 該參數能夠放在http區域, 也能夠訪問server或location區域) 若是後臺Tomcat處理報錯拋出404,想把這個狀態叫Nginx反饋給客戶端或者重定向到某個鏈接. 好比在本身的Linux服務器上部署了tomcat的一個項目,使用Nginx進行的代理,訪問項目不存在的頁面時,出現的是Nginx默認的404頁面, 如今要配置本身定義的404頁面進行提示 配置以下: [root@localhost ~]# cat /data/nginx/conf/vhost/test.conf upstream tomcat { ip_hash; server 127.0.0.1:8080 weight=20 max_fails=2 fail_timeout=30s; } server { listen 80; server_name www.test.com; access_log /data/nginx/logs/access.log main; error_log /data/nginx/logs/error.log; location / { # 即把www.test.com的首頁設定爲index.html (默認狀況下tomcat的首頁是index.jsp, 這裏在tomcat下的webapp/ROOT下加了index.html) if ($request_uri ~* '^/$') { rewrite .* http://www.test.com/index.html redirect; } #關鍵參數(好比加下面這一行的參數配置):這個變量開啓後,咱們才能自定義錯誤頁面,當後端返回404,nginx攔截錯誤定義錯誤頁面 proxy_intercept_errors on; proxy_pass http://tomcat; proxy_set_header HOST $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for; } error_page 404 /404.html; location = /404.html { root /mnt/error; } } 配置解釋: if ($request_uri ~* "^/$") 表示url中只有域名,後面不跟任何東西,好比www.test.com。 if ($request_uri ~* "test") 表示域名後面那串兒只要包含test這個關鍵詞,就可匹配成功。好比www.test.com/pan/beta/test3 上面的配置表示: 當訪問http://www.test.com 時(即url只有一個完整的域名) 時, 頁面跳轉到tomcat跟下的index.html (即tomcat的webapp/ROOT/index.html, tomcat的默認首頁通常是webapp/ROOT/index.jsp) 也就是訪問http://www.test.com, 顯示爲http://www.test.com/index.html, 這個index.html是tomcat的webapp/ROOT/index.html 當訪問http://www.test.com/* 時, 跳轉到http://127.0.0.1:8080/* , 好比訪問 http://www.test.com/index.jsp, 跳轉到http://127.0.0.1:8080/index.jsp, 當訪問http://www.test.com/* 的頁面時, 頁面不存在, 則顯示404錯誤頁面, 錯誤頁面文件爲/mnt/error/404.html [root@localhost ~]# ll /usr/local/tomcat8/webapps/ROOT/index.html -rw-r--r-- 1 root root 21 Dec 19 16:32 /usr/local/tomcat8/webapps/ROOT/index.html [root@localhost ~]# ll /usr/local/tomcat8/webapps/ROOT/index.jsp -rw-r--r-- 1 root root 12513 Jun 29 10:44 /usr/local/tomcat8/webapps/ROOT/index.jsp [root@localhost ~]# ll /mnt/error/404.html -rw-r--r-- 1 root root 31 Dec 19 17:12 /mnt/error/404.html [root@localhost ~]# /data/nginx/sbin/nginx -s reload ------------------------------------------------------------------------------------------------------------------- 這裏注意下: 看下面這個狀況的錯誤頁面本地跳轉配置 [root@localhost ~]# cat /data/nginx/conf/nginx.conf .......... http { proxy_intercept_errors on; [root@localhost ~]# cat /data/nginx/conf/vhosts/test.conf server { listen 80; server_name www.test.com; access_log /data/nginx/logs/access.log main; error_log /data/nginx/logs/error.log; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header REMOTE-HOST $remote_addr; 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 20m; } location /upload { root /data/web; index index.html index.htm; } #error_page 404 /404.html; error_page 500 502 503 504 /404.html; error_page 404 /404.html; location = /404.html { root /data/web/error; } } [root@localhost ~]# cat /data/web/error/404.html Sorry, sir, this page does not exist! Excuse me ~ [root@localhost ~]# /data/nginx/sbin/nginx -s reload 當8080端口的tomcat服務沒有開啓時, 訪問http://www.test.com , 則會出現定義在/data/web/error/404.html錯誤頁面內容 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ================================================ 第三種:反向代理的錯誤頁面 (nginx代理的後端是php解析的頁面, 使用fastcgi_intercept_errors on參數, 該參數能夠放在http區域, 也能夠訪問server或location區域) Nginx解析php代碼的錯誤頁面, 若是後端是php解析的,須要加一個變量fastcgi_intercept_errors on進行錯誤頁面提示, 不然php頁面則顯示爲空白頁! 在http段中加一個變量 fastcgi_intercept_errors on 就能夠了。 [root@localhost ~]# vim /data/nginx/conf/nginx.conf ......... http { fastcgi_intercept_errors on; 接着指定一個錯誤頁面 [root@localhost ~]# vim /data/nginx/conf/vhosts/test.conf ........ error_page 404 /404.html; location = /404.html { root /mnt/error; } 錯誤頁面404.html 放在/mnt/error下面 若是指定404錯誤時跳轉到其餘的一個錯誤頁面, 配置爲 [root@localhost ~]# vim /data/nginx/conf/vhosts/test.conf ........ error_page 404 /404.html; error_page 404 = http://www.test.com/error.html; ================================================================= 舒適提示: 配置proxy_intercept_errors on時, 配置的錯誤頁面表示的是當服務器返回的狀態碼爲咱們配置的狀態碼時,才進行的頁面跳轉。 如:服務器中沒有xxxx.do接口時,訪問了這個接口,配置了proxy_intercept_errors on則也會進行頁面跳轉 若是服務器中沒有開啓服務,則配置proxy_intercept_errors on無用,則須要再添加fastcgi_intercept_errors on配置, 這樣的話,出現頁面錯誤時也會進行跳轉 總結: =====什麼是404頁面====== 若是碰巧網站出了問題,或者用戶試圖訪問一個並不存在的頁面時,此時服務器會返回代碼爲404的錯誤信息,此時對應頁面就是404頁面。 404頁面的默認內容和具體的服務器有關。若是後臺用的是NGINX服務器,那麼404頁面的內容則爲:404 Not Found NGINX下如何自定義404頁面 1) 更改nginx.conf在http定義區域加入: proxy_intercept_errors或者fastcgi_intercept_errors 2) 更改nginx.conf,在server 區域加入: error_page 404 /404.html 或者 error_page 404 =http://www.xxx.com/404.html 3) 更改後重啓nginx,,測試nginx.conf正確性 #502 等錯誤能夠用一樣的方法來配置。 配置以下: error_page 500 502 503 504 /50x.html; location = /50x.html { root /mnt/error; } 或是 error_page 500 501 502 503 504 @errpage; location @errpage { access_log logs/access.log maintry; proxy_pass url; } 注意事項: 1) 要添加:fastcgi_intercept_errors on 或者 proxy_intercept_errors 默認: fastcgi_intercept_errors off 添加位置: http, server, location 默認狀況下,nginx不支持自定義404錯誤頁面,只有這個指令被設置爲on,nginx才支持將404錯誤重定向 這個指令指定是否傳遞4xx和5xx錯誤信息到客戶端,或者容許nginx使用error_page處理錯誤信息。你必須明確的在error_page中指定處理方法使這個參數有效 2) 不要出於省事或者提升首頁權重的目的將首頁指定爲404錯誤頁面,也不要用其它方法跳轉到首頁 3) 自定義的404頁面必須大於512字節,不然可能會出現IE默認的404頁面。例如,假設自定義了404.html,大小隻有11個字節(內容爲:404錯誤) ===== fastcgi_intercept_errors 參數===== 語法:fastcgi_intercept_errors on|off 默認值:fastcgi_intercept_errors off 使用字段:http, server, location 這個指令指定是否傳遞4xx和5xx錯誤信息到客戶端,或者容許nginx使用error_page處理錯誤信息。 你必須明確的在error_page中指定處理方法使這個參數有效,正如Igor所說「若是沒有適當的處理方法,nginx不會攔截一個錯誤,這個錯誤不會顯示本身的默認頁面,這裏容許經過某些方法攔截錯誤。 ===== f注意搞清楚下面狀況===== f 404.html:上游服務器提供的特定404頁面內容,當nginx:80訪問上游服務器資源不存在(返回404),要求顯示的內容頁面。 404_default.html:上游服務器默認404頁面。 配置以下: error_page 404 /404.html; location = /404.html { root /mnt/error; } 或者 error_page 404 /404_default.html; location = /404_default.html { root /mnt/error; } 50x.html:上游服務器提供的特定50x頁面內容,當nginx:80訪問上游服務器出現50x錯誤(包含500, 502, 503和504),要求顯示的內容頁面。 50x_default.html:上游服務器提供的處理50x的默認頁面 配置以下: error_page 50x /50x.html; location = /50x.html { root /mnt/error; } 或者 error_page 50x /50x_default.html; location = /50x_default.html { root /mnt/error; }
18. nginx實現動靜分離
將靜態資源放在 A 主機的一個目錄上,將動態程序放在 B 主機上,同時在 A 上安裝 Nginx 而且在 B 上安裝 Tomcat。配置 Nginx,當請求的是 html、jpg 等靜態資源時,就訪問 A 主機上的靜態資源目錄;當用戶提出動態資源的請求時,則將請求轉發到後端的 B 服務器上,交由 Tomcat 處理,再由 Nginx 將結果返回給請求端。
提到這,可能會有疑問,動態請求要先訪問 A,A 轉發訪問 B,再由 B 返回結果給 A,A 最後又將結果返回給客戶端,這是否是有點多餘。初看的確多餘,可是這樣作至少有 2 點好處。第一,爲負載均衡作準備,由於隨着系統的發展壯大,只用一臺 B 來處理動態請求顯然是是不夠的,要有 B1,B2 等等才行。那麼基於圖 2 的結構,就能夠直接擴展 B1,B2,再修改 Nginx 的配置就能夠實現 B1 和 B2 的負載均衡。第二,對於程序開發而言,這種結構的程序撰寫和單臺主機沒有區別。咱們假設只用一臺 Tomcat 做爲服務器,那麼凡是靜態資源,如圖片、CSS 代碼,就須要編寫相似這樣的訪問代碼:<img src=」{address of A}/a.jpg」>,當靜態資源過多,須要擴展出其餘的服務器來安放靜態資源時,訪問這些資源就可能要編寫這樣的代碼:<img src=」{address of C}/a.jpg」>、<img src=」{address of D}/a.jpg」>。能夠看到,當服務器進行變動或擴展時,代碼也要隨之作出修改,對於程序開發和維護來講很是困難。而基於上面的結構,程序都只 要 <img src=」a.jpg」>,無需關心具體放置資源的服務器地址,由於具體的地址 Nginx 爲幫您綁定和選擇。
動靜分離的nginx配置以下:
# 轉發的服務器,upstream 爲負載均衡作準備 upstream tomcat_server{ server 172.16.50.60:8080 weight=1 max_fails=2 fail_timeout=2; } server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root /data/web; index index.html index.htm; } # 靜態請求直接讀取 location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|js|css)$ { root /data/web; expires 30d; #緩存時間,即有效時間 } # 動態請求的轉發 location ~ .*.jsp$ { proxy_pass http://tomcat_server; proxy_set_header Host $host; } } ============================================================= 若是還有php文件, 則配置添加以下: upstream php { server 172.16.50.15 weight=1 max_fails=2 fail_timeout=2; server 172.16.50.16 weight=1 max_fails=2 fail_timeout=2; } ....... location ~* \.php$ { fastcgi_proxy http://php; } ==================================================================
18. nginx配置中關於url的幾個變量的區別 (如$request_uri , $uri 和 $document_uri )
$request_uri 這個變量等於從客戶端發送來的原生請求URI,包括參數。它不能夠進行修改。$uri變量反映的是重寫後/改變的URI。不包括主機名。 其實這個$request_uri變量指的就是完整url中刨去最前面$host剩下的部分. 好比http://www.baidu.com/pan/beta/test1?fid=3這個url地址,去掉www.baidu.com剩下的就是了,日誌裏會看到打印出來的$request_uri, $request_uri其實指的就是/pan/beta/test1?fid=3 以下匹配規則: if ($request_uri ~* "^/$") 表示url中只有域名,後面不跟任何東西,好比www.baidu.com。 if ($request_uri ~* "test") 表示域名後面那串兒只要包含test這個關鍵詞,就可匹配成功。好比www.baidu.com/pan/beta/test3 $uri 這個變量指當前的請求URI,不包括任何參數。這個變量反映任何內部重定向或index模塊所作的修改。 注意,這和request_uri不一樣,因$request_uri是瀏覽器發起的不作任何修改的原生URI。不包括協議及主機名。 好比http://www.baidu.com/pan/beta/test1?fid=3這個url地址,日誌裏會看到打印出來的$uri其實指的就是/pan/beta/test1 $document_uri 這個變量等同於$uri. 例如:"/pan/beta/test1" 總而言之: $request_uri變量指的則是請求的整個字符串,包含了後面的query_string的。 $uri變量: 指的是請求的文件和路徑,不包括"?"或者"#"以後的東西 例如, 訪問http://www.kevin.com/stat.php?id=1585378&web_id=1585378 則這三個變量分別指的是: $request_uri: /stat.php?id=1585378&web_id=1585378 $uri: /stat.php $document_uri: /stat.php