Nginx是目前比較主流的HTTP反向代理服務器(其企業版提供了基於TCP層的反向代理插件),對於構建大型分佈式web應用,具備舉足輕重的做用。簡單來講,nginx有2個主要的功能:動/靜態資源分離、負載均衡。javascript
動/靜態資源分離:nginx支持正則表達式以區分靜態資源或者動態資源,其中動態資源能夠進一步轉發給後端的proxy server,而靜態資源則能夠在nginx層面使用本地緩存策略或者重定向(類CDN)到其餘nginx上。css
負載均衡:對於動態資源而言,若是有多個proxy server,那麼nginx將會根據必定的算法選擇合適的server,並轉發請求,最終將客戶端request相對均衡的分發給多個server。html
Nginx做爲「單點」,面向客戶端請求,並將請求轉發給後端的某個server,由於server能夠有多個,那麼從總體而言,提高了站點的「資源整合」能力,提高了站點的總體吞吐能力;但由於受限於nginx自己的IO模型,並無「下降」對物理資源的消耗(即性能開支);一般nginx做爲整個站點的「避雷針」和導流通道,它應該被架設在物理資源較爲優越的機器上,好比8U物理機,32核心,64G內存,對磁盤要求相對較低,對CPU、內存、網卡帶寬有較高的要求,由於nginx不只須要和客戶端請求創建連接,並且還須要與後端proxy server創建連接而且負責流量輸入、輸出(這和LVS、Haproxy有本質區別),這種雙倍的連接創建,就要求機器具備較高的內存和CPU,若是你的nginx還有大量的「靜態資源」cache,還須要使用高速、高容量的磁盤。由於nginx節點最終爲全部proxy server流量的總和,那麼它應該具備更高的網卡帶寬。前端
爲了不資源競爭,應該避免nginx和web server部署在同一個節點上,由於web server一般爲CPU和內存高耗型,這會大大下降nginx的代理能力。java
1) 在中小型應用中(PV在KW級別,單一垂直web應用),一般一個nginx代理多個(組)server便可。node
2)對於大中型應用,一個nginx將沒法支撐所有的流量,咱們將會採用多個nginx代理(複製了1)中的架構模型),並在nginx前端繼續構建高性能的分流設備,好比LVS、Haproxy等更低層的軟/硬件負載均衡器,這種負載均衡器一般只是「轉發」,而不涉及到流量的輸出,因此轉發效率將會更高,承載能力更強。linux
3)不管什麼時候,咱們也不但願nginx存在單點故障問題,那麼一般咱們還須要使用keepalived(其餘同類型技術,VIP)來提升nginx節點的可用性,即Master-backup模式。nginx
4)當有多個nginx時,爲了提高後端server的代理能力,一般還會讓多個nginx之間交叉重疊代理後端的server。git
1、經常使用模塊github
在nginx 中,有幾個經常使用的模塊(module):
2、安裝(mac下)
接下來,咱們就嘗試安裝nginx,從官網下載最新版1.8.0壓縮包,並按照以下步驟一次安裝,本人所使用的平臺爲mac OS(很遺憾,mac下安裝這些軟件,仍是至關的費勁)。爲了方便起見,咱們將上述經常使用的module一次性所有安裝或者加載(避免之後從新增長module帶來的麻煩)。下文中所下載的軟件都先保存到/usr/local/src下。
一、下載ngx_cache_purge模塊:http://labs.frickle.com/nginx_ngx_cache_purge/,解壓後保存在本地目錄。
二、下載ngx-http-concat模塊:https://github.com/alibaba/nginx-http-concat,解壓後保存在本地目錄。
三、下載nginx並解壓,保存在/usr/local/src,重命名爲「nginx-1.8.0-src」。
四、configure操做,經過--prefix指定nginx最終的可執行文件copy到哪一個目錄,這個目錄不須要提早建立。
極有可能你會獲得一個錯誤「./configure: error: the HTTP rewrite module requires the PCRE library.」,這意味着若是須要安裝rewrite模塊,那麼就須要安裝PCRE包(perl正則表達式)。
而後你還會獲得一個錯誤「./configure: error: the HTTP image filter module requires the GD library.」,GD包主要用於圖形處理,這個須要手動安裝。安裝GD以前,須要依次安裝libpng、libjpeg,freetype,zlib(mac下不須要安裝,默認已經有了)。
在安裝libgd時,必須指定jpeg,png,freetype這些lib的位置,不然此後在nginx安裝時會報錯:
上述lib安裝完畢以後,而後再次運行3)中的nginx的configure指令,應該就沒有錯誤,而後依次執行「make」 「make install」,此後咱們會在「/usr/local/nginx-1.8.0」目錄下看到相關的可執行文件、配置文件等。若是確實安裝成功,那麼咱們此前的「nginx-1.8.0-src」便可刪除,此後的操做只須要在安裝後的文件中進行便可。
五、測試運行
進入sbin目錄,執行「./nginx」,啓動nginx,若是出錯,請到logs目錄下查看緣由。而後在瀏覽器中輸入「127.0.0.1」(無需端口),你將會獲得nginx的歡迎頁。
接下來,咱們將依次介紹nginx的幾個經常使用的模塊,在認識如何配置nginx的同時,簡單瞭解nginx的工做原理。
咱們能夠經過「./nginx -V」查看nginx的configure信息。
「./nginx -t」用於檢測配置文件是否合法。
「./nginx -s stop」:關閉。
「./nginx -s quit」:優雅關閉。
「./nginx -s reopen」:從新打開log文件
「./nginx -s reload」:從新加載配置信息,咱們在修改了conf文件以後,一般使用reload便可直接加載,無需重啓nginx。
nginx會啓動一個master進程,和「worker_processes」個worker進程,其中master進程主要的做用就是「加載、評定配置信息」、「維護worker進程」,worker進程用於處理實際的request,nginx基於平臺的event模型,向worker進程分發request。
當master進程收到reload信號時,首先檢測配置文件的合法性,而後嘗試使用新的配置信息;若是成功,master將啓動新的worker進程,並向原來的worker進程發消息請求他們shutdown,此後request將會被抓發給新的worker進程,對於原來的worker將本身已經accept的請求處理完以後即關閉;若是配置文件有問題,master將會回滾配置的更改,而worker進程不受任何影響。
六、配置文件樣例
上面的配置信息應該是最基本的,基本上nginx可以對靜態頁面作代理,下文中全部的模塊都基於這個配置模板。
3、代理簡析
nginx一個重要的能力就是靜態文件的代理(或cache),包括html、images等,這些靜態文件一般放置在本地,好比:/data/www(一些html文件,css,js等),/data/images(圖片文件)。
root」表示文件所在的本地路徑,最終請求的uri將會被添加到root路徑以後,造成完整的文件路徑,好比「127.0.0.1/images/header.jpg」,其uri爲「images/header.jpg」,那麼最終將會訪問本地的「/data/images/header.jpg」(若是本地文件沒有訪問權限,將會拋出「Permission denied」)。此處還涉及到location的匹配優先級的問題,就像「/images/header.jpg」對於location爲「/」和「/images」都匹配,在這種狀況下,nginx將會選擇「最長前綴」的哪個,即「/images」;此外,location還能支持正則表達式,因此匹配的規則將會比較複雜,咱們稍後詳解location。
對於動態代理,須要配置一個(或一組,經過upstream模塊支持)web server,nginx接收客戶端請求(能夠對header進行修改),而後傳遞給web server,並等待接收proxy server的響應內容,而後再把response發送給客戶端(能夠對response的內容或者header進行修改),在此過程當中,nginx須要與客戶端、web server均要創建連接,nginx就像一個「轉發橋」,只是負責將請求,根據location或者其餘規則,匹配到一個合適的web server上。
proxy_pass將請求轉發給web server,不過這個指令還有更多的意義,咱們稍後詳解upstream、proxy模塊。動態代理,即實際處理請求(響應數據的server)的server在運行時經過必定的算法計算獲得的,並且還能夠根據請求的參數特徵來修改response的內容;一般咱們會指定多個web server,根據必定的「負載均衡」算法選取其中一個負責處理實際的請求。
「server_name」這個指令很是有用,nginx一般根據http請求header中的「Host」字段與「server_name」列表匹配,斷定使用哪一個「server」配置,而後根據uri匹配location,斷定將次request交給哪一個web server處理。關於server_name的匹配規則,還須要必定的瞭解。(以下部分配置樣例中省略了部分無關的信息)
對於指定的請求,nginx從header中host值,將按照以下順序進行匹配:
1)精確的全限定名:好比server_name爲「www.exmaple.org」,「example.org」。
2)以「*」開頭的最長的通配名稱:好比server_name爲「*.exmaple.org」。
3)以「*」結束的最長的通配名稱:好比server_name爲「mail.*」。
4)首個匹配的正則表達式。nginx中正則表達式以「~」或者「~*」開頭,咱們稍後詳解nginx的正則格式。
注意,在nginx中,通配表達式和正則表達式被認爲是不一樣的,通配表達式必須以「*」開頭或者結束,且「*」不能在字符串的中間出現,好比「www.*.example.org」是不合法的;不然應該在正則表達式中使用「*」,好比「~^w.*\.exmaple\.org$」,注意若是在正則表達式中使用字符串「.」,應該須要轉義爲「\.」,不然「.」是被做爲正則表達式中特殊模式(即匹配任意字符串);通配表達式,「*」能夠匹配任意多個部分,好比「*.example.org」能夠匹配「www.exmaple.org」、「www.sub.exmaple.org」;那麼對於「.example.org」這種格式被認爲是一種特殊的正則表達式,它能夠匹配「exmaple.org」、「*.example.org」。
上文中提到,nginx中正則表達式必須以「~」開頭(或者~*開頭,表示字符大小寫敏感)、「^」、「$」結尾,這三個特殊符號構成nginx(或者說是PCRE)正則表達式,不然被認爲是普通的「全限定名」。若是你瞭解過正則表達式,其實這些仍是很是容易理解的,不過若是正則表達式中包括「{」、「}」表示匹配次數區間,那麼整個表達式都須要用引號包含,不然會編譯錯誤。
正則表達式中可使用"?<name>"這種格式,在PCRE中稱爲「命名捕獲」(named captures),那麼「name」能夠做爲當前context中的一個變量使用。在nginx中還可使用「數字」類型的命名捕獲。
咱們還須要對待那些特殊的狀況,好比請求的header中沒有「Host」或者爲空,那麼能夠用一個空字符串來匹配這種請求:
固然有些時候,咱們還會使用IP去訪問一個nginx(沒有配置host解析,一般在測試環境),那麼咱們咱們請求的「Host」就是一個IP字符串,那麼咱們仍然能夠按照這種規則配置server_name。
如上述例子所示,「default_server」表示爲若是沒有任何匹配的server_name時,將選擇此server來處理。其中server_name若是配置爲「_」,則表示此server匹配全部的「Host」,這些Host僅爲那些不能經過「精確全限定名」、「通配表達式」、「正則表達式」匹配的。
根據server偵聽的端口號,將會把「精確匹配」、「以*開頭的通配表達式」、「以*結尾的通配表達式」保存在三個hashtable中(cache),這個hashtable的大小能夠經過配置文件調整;針對一個host,將會首先使用「精確匹配」,若是沒有找到相應的server_name,將會從「以*開頭的通配表達式」中查找,而後再從「已*結尾的通配表達式」中查找;從「通配表達式」的hashtable中查找,要慢於「精確匹配」,不過對於「.example.org」這種格式會被保存在「通配表達式」的hashtable中,而不是保存在「精確匹配」的hashtable中。對於「正則表達式」時最慢的一種方式,也是最後參與匹配的,將會根據它們在配置文件中的順序,依次去匹配。基於這些緣由,比較好的辦法就是儘量的使用「精確全限定名」,好比:
而不是像這樣簡單的配置:
若是你定義了較多的server配置或者較長的server_name字符串,那麼就須要經過「server_names_hash_max_size」(會影響server_name的個數)、「server_names_hash_bucket_size」(影響server_name的字符串長度)來調整配置,不然會拋出錯誤,咱們不須要貿然去調整這兩個參數,直到它出錯。
4、負載均衡
使用nginx,其實還對其「負載均衡」的特性比較看重。一般咱們有多個web server對等部署,nginx將會經過「負載均衡」模塊將請求轉發給合適的web server,最終提高了web站點的總體吞吐能力,同時也提升了可用性。須要注意,nginx目前是Http層面的負載均衡器,在1.9V以後將提供TCP層面的負載均衡支持。以下爲nginx內置的負載均衡算法:
1)round-robin:輪詢,request將會依次有序的分發給web server。one by one!默認使用此算法。
2)least-connected:最小鏈接數,請求將會被分發給當前連接數最小的server。配置名「least_conn」。
3)ip-hash:根據請求的客戶端IP做爲hashing key,來斷定選擇哪一個server。配置名「ip_hash」。
上述配置,就是一個簡單的「負載均衡」的樣例,首先在一個「upstream」區塊中聲明server列表,而後在proxy_pass指令中使用它;若是沒有聲明「負載均衡」算法,那麼默認就是用「round-robin」,其餘可選值爲「least_conn」、「ip_hash」,「負載均衡」算法須要在upstream區塊的首行聲明。
「least_conn」算法可讓全局的性能開支,在多個server之間趨於平衡,由於不一樣的server可能在物理性能上就有差距,並且不一樣的request處理耗時也不盡相同;若是但願處理比較快的server可以儘量的接收更多的請求,那些負載較高的server也能穩步推動(後續咱們會提到流量控制),那麼「least_conn」算法將很是適合。一般咱們在production環境中,均採用此算法。
「least_conn」和「round-robin」算法,將會把一個客戶端(來自同一個IP)的請求分發給不一樣的server上,這在某些狀況下並不妥,好比「粘性session」,同一個客戶端的請求應該被轉發給同一個server(除非此server失效後,纔會被轉發到其餘server),不然session會話中的數據將會丟失。那麼「ip_hash」算法將比較適合。不過基於殘酷的現實,粘性session的設計方案並不通用。
可以影響負載均衡策略的還有一個重要的參數:權重;「權重」用來標記某個server承載請求的「優先級」,一般權重越高的server將優先得到客戶端請求,事實上「權重」也是表示一個server「承載」能力的大小,咱們一般能夠對硬件配置較高的server給予較高的權重,這有點像粗顆粒的「虛擬化」,若是一個server的硬件配置是另外一個的2倍,那麼能夠將權重值設置爲其2倍。
默認upstream中全部的server權重都同樣,那麼「負載均衡」算法將平等對待它們。
對於上述配置,每5個請求,將有3個分發給「192.168.1.110」,其餘兩個server各一個。上述提到的三種負載均衡算法中,均可以使用weight。
「健康監測」對於負載均衡是必須的,這是提供可用性、「故障遷移」的必要手段。好比當某個server失效,請求未能正常處理,那麼咱們應該將分發給那些「正常」的server,並將故障的server從列表中移除,直到它恢復,以免後續更多的請求處理失敗。nginx當與一個server創建連接失敗後,會在「fail_timeout」時間內最多嘗試「max_fails」次,若是仍爲失敗,則將次server標記爲「failed」,並從服務列表中移除。默認「max_fails」爲1,若是「max_fails」爲0,則表示關閉「健康檢測」;「fail_timeout」(默認位10s)表示檢測多久後被標記爲「failed」,nginx會以優雅的方式檢測那些失效的server,若是它們再次上線,則將它們標記爲「alive」,便可繼續提供服務。
更多的關於「負載均衡」配置方式,咱們將在下文「upstream」模塊中詳解。
5、計量單位
nginx配置文件中,對於表示「數據尺寸」的數字後,能夠跟上「k」、「m」、「g」等單位縮寫字母,無單位後綴表示「字節」。對於表示「時間」的數字,可使用「ms」、「s」、「m」(分鐘)、h、d(天)、w(周)、M(月)、y(年),咱們還能以組合的方式使用它們,好比「1h 30m」,表示一小時30分鐘,至關於「90m」或者「5400s」,無單位後綴表示「秒」。以下例:
6、HTTPS配置
https忽然風靡起來,就連小論壇也開始用https,顯的很技術派,彷佛它的低性能的缺點並無想象的那麼可怕。在實際環境中,nginx和後端的web server都可以支持htps,爲了架構的簡單性,以及不但願web協議干擾程序的實現,咱們一般在nginx這一次支持https,而在web server層(好比tomcat)則繼續使用http協議。配置樣例以下:
不管如何,你在使用HTTPS以前,須要開啓SSL,若是是線上應用,還須要從第三方機構購買一個合法的認證包(若是本身生成,其實並無什麼卵用),這個包裏將會包含crt和key兩個文件,而後根據上述nginx樣例將文件的路徑配置正確便可,須要提醒,nginx須要有訪問這兩個文件的權限。
SSL操做須要消耗額外的CPU資源,主要在SSL握手階段,有2種方式能夠減小每一個客戶端的這種操做:1)開啓連接的keepalive選項(http 1.1),那麼一個客戶端能夠經過一個(次)連接發送多個請求,事實上達成了連接重用的目的,減小了建立連接和「握手」的次數。 2)重用SSL session參數,以免此後的子連接再進行握手操做,經過「ssl_session_cache」配置,session將會被保存在cache中,能夠在workers進程之間共享,1M的cache空間能夠保存大概4000個sessions,緩存生命週期默認爲5分鐘,能夠經過「ssl_session_cache」修改。「ssl_session_cache shared:SSL:10m」表示cache能夠在多個workers進程之間共享,cache名位「SSL」,緩存大小爲10M(數據尺寸,不是10分鐘)。
上述配置,任何http請求都會被rewrite成https,不過在proxy_pass分發給後端web server時使用http協議,這是一種比較經常使用的方式,因此讓你的網站支持https,只須要在nginx層作認證便可,不須要調整web server的配置。
7、其餘
在描述nginx的指令以前,咱們基本熟悉了nginx指令的配置方式:「<指令名稱> 值 [可選參數名=參數值];」,以「;」結束,一個區塊咱們能夠包含多個指令,那麼這種區塊稱爲context(上線文),nginx中經常使用的區塊有「http」、「events」、「server」、「upstream」、「location」等,最外層的context稱之爲「main」,context一般是有繼承關係,好比「location」須要包含在「server」中。「#」表示行註釋。
在nginx配置文件中,若是配置項表示路徑,好比「root /data/images」,若是爲相對路徑,則起始與nginx根目錄。
一個指令能夠被配置在多個context下,好比「root」:
那麼根據context的繼承關係,子context的指令將覆蓋其父context,同理,其餘指令也將是如此。
8、nginx常規配置模板
以「exmaple.org」爲例,以下爲基於upstream負載均衡模式的配置:
上述配置中,對後端web server返回的靜態類型文件,讓瀏覽器緩存15天,對於jhtml格式的動態文件不緩存。
9、基於HTTPS配置核心配置
10、對於文件系統而言,基於nginx緩存的配置