Nginx簡(jiǎn)介
Nginx (發(fā)音為“Engine-x”)是一種開源軟件,最初被設(shè)計(jì)為高性能Web服務(wù)器。今天,Nginx可以完成其他一些任務(wù),包括緩存服務(wù)器,反向代理服務(wù)器,負(fù)載平衡器等等。
WEB服務(wù)器
目前主流使用的web服務(wù)器軟件,主要有Apache、nginx、Tomcat、iis等,在全球范圍內(nèi)來說,Apache是現(xiàn)有的最流行的Web服務(wù)器,但是在高流量網(wǎng)站中最流行的Web服務(wù)器確實(shí)nginx,在我國(guó)不管是大中小互聯(lián)網(wǎng)公司,主流選擇的也是nginx作為web服務(wù)器軟件。一份來?.NETcraft的調(diào)查中,發(fā)現(xiàn)Apache的使用率為31.54%,Nginx的使用率為26.20%。
HTTP代理服務(wù)器
HTTP代理,分兩類:一種的正向代理,一種是反向代理。
正向代理
正向代理(Forward Proxy)最大的特點(diǎn)是,客戶端非常明確要訪問的服務(wù)器地址,它代理客戶端,替客戶端發(fā)出請(qǐng)求。
假設(shè)客戶端想要訪問 google,它明確知道待訪問的服務(wù)器地址是 https://www.google.com/,但由于條件限制,它找來了一個(gè)能夠訪問到 Google 的”朋友”:代理服務(wù)器??蛻舳税颜?qǐng)求發(fā)給代理服務(wù)器,由代理服務(wù)器代替它請(qǐng)求 Google,最終再將響應(yīng)返回給客戶端。這便是一次正向代理的過程,該過程中服務(wù)器并不知道真正發(fā)出請(qǐng)求的是誰(shuí)。
反向代理
那么,隨著請(qǐng)求量的爆發(fā)式增長(zhǎng),服務(wù)器覺得自己一個(gè)人始終是應(yīng)付不過來,需要兄弟服務(wù)器們幫忙,于是它喊來了自己的兄弟以及代理服務(wù)器朋友。此時(shí),來自不同客戶端的所有請(qǐng)求實(shí)際上都發(fā)到了代理服務(wù)器處,再由代理服務(wù)器按照一定的規(guī)則將請(qǐng)求分發(fā)給各個(gè)服務(wù)器。
這就是反向代理(Reverse Proxy),反向代理隱藏了服務(wù)器的信息,它代理的是服務(wù)器端,代其接收請(qǐng)求。換句話說,反向代理的過程中,客戶端并不知道具體是哪臺(tái)服務(wù)器處理了自己的請(qǐng)求。如此一來,既提高了訪問速度,又為安全性提供了保證。
在這之中,反向代理需要考慮的問題是,如何進(jìn)行均衡分工,控制流量,避免出現(xiàn)局部節(jié)點(diǎn)負(fù)載過大的問題。通俗的講,就是如何為每臺(tái)服務(wù)器合理的分配請(qǐng)求,使其整體具有更高的工作效率和資源利用率。
基于nginx的反向代理,可以實(shí)現(xiàn)分布式(不同子域名訪問不同的服務(wù)后端節(jié)點(diǎn))和負(fù)載均衡(相同的域名訪問多個(gè)相同的后端節(jié)點(diǎn))
反向代理和正向代理的區(qū)別:
- 正向代理:針對(duì)客戶端而言,代理服務(wù)器代理客戶端,轉(zhuǎn)發(fā)請(qǐng)求,并將獲得的內(nèi)容返回給客戶端。
- 反向代理:針對(duì)客戶端而言,代理服務(wù)器就像是原始服務(wù)器,代理集群的web節(jié)點(diǎn)服務(wù)器返回結(jié)果。
負(fù)載均衡器
負(fù)載均衡也是Nginx常用的一個(gè)功能,基于nginx反向代理。負(fù)載均衡其意思就是分?jǐn)偟蕉鄠€(gè)操作單元上進(jìn)行執(zhí)行,例如Web服務(wù)器、FTP服務(wù)器、企業(yè)關(guān)鍵應(yīng)用服務(wù)器和其它關(guān)鍵任務(wù)服務(wù)器等,從而共同完成工作任務(wù)。簡(jiǎn)單而言就是當(dāng)有2臺(tái)或以上服務(wù)器時(shí),根據(jù)規(guī)則隨機(jī)的將請(qǐng)求分發(fā)到指定的服務(wù)器上處理,負(fù)載均衡配置一般都需要同時(shí)配置反向代理,通過反向代理跳轉(zhuǎn)到負(fù)載均衡。Nginx目前支持自帶3種負(fù)載均衡策略(輪詢、加權(quán)輪詢、IP哈希),還有2種常用的第三方策略(fair、url哈希)。
緩存服務(wù)器
nginx可以實(shí)現(xiàn)圖片、css、js等靜態(tài)資源文件的緩存,nginx作為緩存服務(wù)器時(shí)是搭配nginx作為反向代理服務(wù)器一起使用的。當(dāng)客戶端第一次通過nginx向后端資源服務(wù)器請(qǐng)求靜態(tài)資源,響應(yīng)給對(duì)應(yīng)的客戶端同時(shí)自身緩存一份,后續(xù)如果請(qǐng)求相同的資源,就不需要再次向后端服務(wù)器請(qǐng)求了,除非緩存被清理或者緩存過期。
Nginx負(fù)載均衡簡(jiǎn)介
負(fù)載均衡(Load Balance),它在網(wǎng)絡(luò)現(xiàn)有結(jié)構(gòu)之上可以提供一種廉價(jià)、有效、透明的方法來擴(kuò)展網(wǎng)絡(luò)設(shè)備和服務(wù)器的帶寬,并可以在一定程度上增加吞吐量、加強(qiáng)網(wǎng)絡(luò)數(shù)據(jù)處理能力、提高網(wǎng)絡(luò)的靈活性和可用性等。用官網(wǎng)的話說,它充當(dāng)著網(wǎng)絡(luò)流中“交通指揮官”的角色,“站在”服務(wù)器前處理所有服務(wù)器端和客戶端之間的請(qǐng)求,從而最大程度地提高響應(yīng)速率和容量利用率,同時(shí)確保任何服務(wù)器都沒有超負(fù)荷工作。如果單個(gè)服務(wù)器出現(xiàn)故障,負(fù)載均衡的方法會(huì)將流量重定向到其余的集群服務(wù)器,以保證服務(wù)的穩(wěn)定性。當(dāng)新的服務(wù)器添加到服務(wù)器組后,也可通過負(fù)載均衡的方法使其開始自動(dòng)處理客戶端發(fā)來的請(qǐng)求。
簡(jiǎn)言之,負(fù)載均衡實(shí)際上就是將大量請(qǐng)求進(jìn)行分布式處理的策略。
負(fù)載均衡是將負(fù)載分?jǐn)偟蕉鄠€(gè)操作單元上執(zhí)行,從而提高服務(wù)的可用性和響應(yīng)速度,帶給用戶更好的體驗(yàn)。對(duì)于Web應(yīng)用,通過負(fù)載均衡,可以將一臺(tái)服務(wù)器的工作擴(kuò)展到多臺(tái)服務(wù)器中執(zhí)行,提高整個(gè)網(wǎng)站的負(fù)載能力。其本質(zhì)采用一個(gè)調(diào)度者,保證所有后端服務(wù)器都將性能充分發(fā)揮,從而保持服務(wù)器集群的整體性能最優(yōu),這就是負(fù)載均衡。
負(fù)載均衡是 Nginx 比較常用的一個(gè)功能,可優(yōu)化資源利用率,最大化吞吐量,減少延遲,確保容錯(cuò)配置,將流量分配到多個(gè)后端服務(wù)器。
Nginx 在 AKF 可擴(kuò)展立方體上的應(yīng)用:
- 在 x 軸上,可以通過橫向擴(kuò)展應(yīng)用服務(wù)器集群,Nginx 基于 Round-Robin 或者 Least-Connected 算法分發(fā)請(qǐng)求。但是橫向擴(kuò)展并不能解決所有問題,當(dāng)數(shù)據(jù)量大的情況下,無(wú)論擴(kuò)展多少臺(tái)服務(wù),單臺(tái)服務(wù)器數(shù)據(jù)量依然很大。
- 在 y 軸上,可以基于 URL 進(jìn)行不同功能的分發(fā)。需要對(duì) Nginx 基于 URL 進(jìn)行 location 的配置,成本較高。
- 在 z 軸上可以基于用戶信息進(jìn)行擴(kuò)展。例如將用戶 IP 地址或者其他信息映射到某個(gè)特定的服務(wù)或者集群上去。
這就是 Nginx 的負(fù)載均衡功能,它的主要目的就是為了增強(qiáng)服務(wù)的處理能力和容災(zāi)能力。
- 當(dāng)一個(gè)應(yīng)用單位時(shí)間內(nèi)訪問量激增,服務(wù)器的帶寬及性能受到影響,影響大到自身承受能力時(shí),服務(wù)器就會(huì)宕機(jī)奔潰,為了防止這種現(xiàn)象發(fā)生,以及實(shí)現(xiàn)更好的用戶體驗(yàn),我們可以通過配置 Nginx 負(fù)載均衡的方式來分擔(dān)服務(wù)器壓力。
- 當(dāng)有一臺(tái)服務(wù)器宕機(jī)時(shí),負(fù)載均衡器就分配其他的服務(wù)器給用戶,極大的增加的網(wǎng)站的穩(wěn)定性。當(dāng)用戶訪問 Web 時(shí)候,首先訪問到的是負(fù)載均衡器,再通過負(fù)載均衡器將請(qǐng)求轉(zhuǎn)發(fā)給后臺(tái)服務(wù)器。
Nginx 作為負(fù)載均衡主要有以下幾個(gè)理由:
- 高并發(fā)連接
- 內(nèi)存消耗少
- 配置文件非常簡(jiǎn)單
- 成本低廉
- 支持 Rewrite 重寫規(guī)則
- 內(nèi)置的健康檢查功能
- 節(jié)省帶寬
- 穩(wěn)定性高
Nginx 工作在網(wǎng)絡(luò)的 7 層,可以針對(duì) HTTP 應(yīng)用本身來做分流策略。支持七層 HTTP、HTTPS 協(xié)議的負(fù)載均衡。對(duì)四層協(xié)議的支持需要第三方插件 -yaoweibin 的 ngx_tcp_proxy_module 實(shí)現(xiàn)了 TCP upstream。
Nginx被稱為動(dòng)態(tài)負(fù)載均衡的主要原因:
- 自身監(jiān)控。 內(nèi)置了對(duì)后端服務(wù)器的健康檢查功能。如果 Nginx Proxy 后端的某臺(tái)服務(wù)器宕機(jī)了,會(huì)把返回錯(cuò)誤的請(qǐng)求重新提交到另一個(gè)節(jié)點(diǎn),不會(huì)影響前端訪問。它沒有獨(dú)立的健康檢查模塊,而是使用業(yè)務(wù)請(qǐng)求作為健康檢查,這省去了獨(dú)立健康檢查線程,這是好處。壞處是,當(dāng)業(yè)務(wù)復(fù)雜時(shí),可能出現(xiàn)誤判,例如后端響應(yīng)超時(shí),這可能是后端宕機(jī),也可能是某個(gè)業(yè)務(wù)請(qǐng)求自身出現(xiàn)問題,跟后端無(wú)關(guān)。
- 可擴(kuò)展性。 Nginx 屬于典型的微內(nèi)核設(shè)計(jì),其內(nèi)核非常簡(jiǎn)潔和優(yōu)雅,同時(shí)具有非常高的可擴(kuò)展性。
- Nginx 是純 C 語(yǔ)言的實(shí)現(xiàn),其可擴(kuò)展性在于其模塊化的設(shè)計(jì)。目前,Nginx 已經(jīng)有很多的第三方模塊,大大擴(kuò)展了自身的功能。nginx_lua_module可以將 Lua 語(yǔ)言嵌入到 Nginx 配置中,從而利用 Lua 極大增強(qiáng)了 Nginx 本身的編程能力,甚至可以不用配合其它腳本語(yǔ)言(如 php 或 Python/ target=_blank class=infotextkey>Python 等),只靠 Nginx 本身就可以實(shí)現(xiàn)復(fù)雜業(yè)務(wù)的處理。
- 配置修改。 Nginx 支持熱部署,幾乎可以做到 7*24 不間斷運(yùn)行,即使運(yùn)行數(shù)個(gè)月也不需要重新啟動(dòng)。能夠在不間斷服務(wù)的情況下,對(duì)軟件版本進(jìn)行進(jìn)行升級(jí)。Nginx 的配置文件非常簡(jiǎn)單,風(fēng)格跟程序一樣通俗易懂,能夠支持 perl 語(yǔ)法。使用nginx –s reload 可以在運(yùn)行時(shí)加載配置文件,便于運(yùn)行時(shí)擴(kuò)容/減容。重新加載配置時(shí),master 進(jìn)程發(fā)送命令給當(dāng)前正在運(yùn)行的 worker 進(jìn)程 worker 進(jìn)程接到命令后會(huì)在處理完當(dāng)前任務(wù)后退出。同時(shí),master 進(jìn)程會(huì)啟動(dòng)新的 worker 進(jìn)程來接管工作。
Nginx負(fù)載均衡策略
Nginx 作為一款優(yōu)秀的反向代理服務(wù)器,可以通過不同的負(fù)載均衡算法來解決請(qǐng)求量過大情況下的服務(wù)器資源分配問題。Nginx 的負(fù)載均衡策略可以劃分為兩大類:內(nèi)置策略 和 擴(kuò)展策略。
- 內(nèi)置策略包含輪詢、加權(quán)輪詢和ip hash等,在默認(rèn)情況下這兩種策略會(huì)編譯進(jìn) Nginx 內(nèi)核,只需在 Nginx 配置中指明參數(shù)即可。
- 擴(kuò)展策略有很多,如fair、通用 hash、consistent hash 等,默認(rèn)不編譯進(jìn) Nginx 內(nèi)核。
|
策略 |
作用 |
|
輪詢 |
按時(shí)間順序逐一分配到不同的后端服務(wù)器,如果后端服務(wù)掛了,能自動(dòng)剔除 |
|
加權(quán)輪詢 |
權(quán)重分配,指定輪詢幾率,weight 值越大,分配到的訪問幾率越高,用于后端服務(wù)器性能不均的情況 |
|
ip_hash |
每個(gè)請(qǐng)求按訪問 IP 的 hash 結(jié)果分配,這樣每個(gè)訪客固定訪問一個(gè)后端服務(wù)器,可以解決動(dòng)態(tài)網(wǎng)頁(yè) session 共享問題。負(fù)載均衡每次請(qǐng)求都會(huì)重新定位到服務(wù)器集群中的某一個(gè),那么已經(jīng)登錄某個(gè)服務(wù)器的用戶再重新定位到另一個(gè)服務(wù)器,其登錄信息將會(huì)丟失,這樣顯然是不妥的 |
|
least_conn |
最少鏈接數(shù),那個(gè)機(jī)器連接數(shù)少就分支 |
|
url_hash |
按照訪問的 url 的 hash 結(jié)果來分配請(qǐng)求,是每個(gè) url 定向到同一個(gè)后端服務(wù)器 |
|
hash 關(guān)鍵值 |
hash 自定義的 key |
|
fair(第三方) |
按后端服務(wù)器的響應(yīng)時(shí)間分配,響應(yīng)時(shí)間短的優(yōu)先分配,依賴第三方插件 nginx-upstream-fair,需要先安裝 |
這里舉出常用的幾種調(diào)度算法策略:
輪詢策略
輪詢策略(默認(rèn)),請(qǐng)求按時(shí)間順序,逐一分配到 Web 層服務(wù),然后周而復(fù)始,如果 Web 層服務(wù)掛掉,自動(dòng)剔除
輪詢?yōu)樨?fù)載均衡中較為基礎(chǔ)也較為簡(jiǎn)單的算法,它不需要配置額外參數(shù)。假設(shè)配置文件中共有 M 臺(tái)服務(wù)器,該算法遍歷服務(wù)器節(jié)點(diǎn)列表,并按節(jié)點(diǎn)次序每輪選擇一臺(tái)服務(wù)器處理請(qǐng)求。當(dāng)所有節(jié)點(diǎn)均被調(diào)用過一次后,該算法將從第一個(gè)節(jié)點(diǎn)開始重新一輪遍歷。
特點(diǎn):由于該算法中每個(gè)請(qǐng)求按時(shí)間順序逐一分配到不同的服務(wù)器處理,因此適用于服務(wù)器性能相近的集群情況,其中每個(gè)服務(wù)器承載相同的負(fù)載。但對(duì)于服務(wù)器性能不同的集群而言,該算法容易引發(fā)資源分配不合理等問題。
upstream backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
weight=number 設(shè)置服務(wù)器的權(quán)重,默認(rèn)為 1,權(quán)重大的會(huì)被優(yōu)先分配。
加權(quán)輪詢
為了避免普通輪詢帶來的弊端,加權(quán)輪詢應(yīng)運(yùn)而生。在加權(quán)輪詢中,每個(gè)服務(wù)器會(huì)有各自的權(quán)重 weight。一般情況下,weight 的值越大意味著該服務(wù)器的性能越好,可以承載更多的請(qǐng)求。該算法中,客戶端的請(qǐng)求按權(quán)值比例分配,當(dāng)一個(gè)請(qǐng)求到達(dá)時(shí),優(yōu)先為其分配權(quán)值最大的服務(wù)器。
特點(diǎn):加權(quán)輪詢可以應(yīng)用于服務(wù)器性能不等的集群中,使資源分配更加合理化。
Nginx 加權(quán)輪詢?cè)创a可見:
ngx_http_upstream_round_robin.c ,源碼分析可參考: 關(guān)于輪詢策略原理的自我理解 。其核心思想是,遍歷各服務(wù)器節(jié)點(diǎn),并計(jì)算節(jié)點(diǎn)權(quán)值,計(jì)算規(guī)則為 current_weight 與其對(duì)應(yīng)的 effective_weight 之和,每輪遍歷中選出權(quán)值最大的節(jié)點(diǎn)作為最優(yōu)服務(wù)器節(jié)點(diǎn)。其中 effective_weight 會(huì)在算法的執(zhí)行過程中隨資源情況和響應(yīng)情況而改變。
upstream backend {
server 127.0.0.1:3000 weight=2;
server 127.0.0.1:3001 weight=1;
}
backup 標(biāo)記為備份服務(wù)器。當(dāng)主服務(wù)器不可用時(shí),將傳遞與備份服務(wù)器的連接。
upstream backend {
server 127.0.0.1:3000 backup;
server 127.0.0.1:3001;
}
IP 哈希(IP hash)
客戶端 IP 綁定:ip_hash 保持會(huì)話,保證同一客戶端始終訪問一臺(tái)服務(wù)器。
ip_hash 依據(jù)發(fā)出請(qǐng)求的客戶端 IP 的 hash 值來分配服務(wù)器,該算法可以保證同 IP 發(fā)出的請(qǐng)求映射到同一服務(wù)器,或者具有相同 hash 值的不同 IP 映射到同一服務(wù)器。
特點(diǎn):該算法在一定程度上解決了集群部署環(huán)境下 Session 不共享的問題。
Session 不共享問題是說,假設(shè)用戶已經(jīng)登錄過,此時(shí)發(fā)出的請(qǐng)求被分配到了 A 服務(wù)器,但 A 服務(wù)器突然宕機(jī),用戶的請(qǐng)求則會(huì)被轉(zhuǎn)發(fā)到 B 服務(wù)器。但由于 Session 不共享,B 無(wú)法直接讀取用戶的登錄信息來繼續(xù)執(zhí)行其他操作。
實(shí)際應(yīng)用中,我們可以利用 ip_hash,將一部分 IP 下的請(qǐng)求轉(zhuǎn)發(fā)到運(yùn)行新版本服務(wù)的服務(wù)器,另一部分轉(zhuǎn)發(fā)到舊版本服務(wù)器上,實(shí)現(xiàn)灰度發(fā)布。再者,如遇到文件過大導(dǎo)致請(qǐng)求超時(shí)的情況,也可以利用 ip_hash 進(jìn)行文件的分片上傳,它可以保證同客戶端發(fā)出的文件切片轉(zhuǎn)發(fā)到同一服務(wù)器,利于其接收切片以及后續(xù)的文件合并操作。
upstream backend {
ip_hash;
server 127.0.0.1:3000 backup;
server 127.0.0.1:3001;
}
最小連接數(shù)策略
least_conn 優(yōu)先分配最少連接數(shù)的服務(wù)器,避免服務(wù)器超載請(qǐng)求過多。
假設(shè)共有 M 臺(tái)服務(wù)器,當(dāng)有新的請(qǐng)求出現(xiàn)時(shí),遍歷服務(wù)器節(jié)點(diǎn)列表并選取其中連接數(shù)最小的一臺(tái)服務(wù)器來響應(yīng)當(dāng)前請(qǐng)求。連接數(shù)可以理解為當(dāng)前處理的請(qǐng)求數(shù)。
upstream backend {
least_conn;
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
最快響應(yīng)時(shí)間策略
fair 依賴于 Nginx Plus,有限分配給響應(yīng)時(shí)間最短的服務(wù)器
當(dāng)我們需要代理一個(gè)集群時(shí)候可以通過下面這種方式實(shí)現(xiàn)。
http {
upstream backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
server {
listen 9000;
server_name localhost;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass backend;
}
}
}
標(biāo)準(zhǔn)配置:
# upstream:該指令用于設(shè)置可以再 proxy_pass 和 fastcgi_pass 指令中使用的代理服務(wù)器
# weight:設(shè)置服務(wù)器的權(quán)重,權(quán)重?cái)?shù)值越高,被分配到的客戶端請(qǐng)求數(shù)越多,默認(rèn)為 1
# max_fails:指定的時(shí)間內(nèi)對(duì)后端服務(wù)器請(qǐng)求失敗的次數(shù),如果檢測(cè)到后端服務(wù)器無(wú)法連接及發(fā)生服務(wù)器錯(cuò)誤(404 錯(cuò)誤除外),則標(biāo)記為失敗,默認(rèn)為 1,設(shè)為數(shù)值 0 將關(guān)閉這項(xiàng)檢測(cè)
# fail_timeout:在經(jīng)歷參數(shù) max_fails 設(shè)置的失敗次數(shù)后,暫停的時(shí)間
# down:標(biāo)記服務(wù)器為永久離線狀態(tài),用于 ip_hash 指令
# backup:僅僅非在 backup 服務(wù)器全部繁忙的時(shí)候才會(huì)啟用
upstream imooc {
server 116.62.103.228:8001 weight=1 max_fails=2 fail_timeout=30s;
server 116.62.103.228:8002;
server 116.62.103.228:8003;
}
server {
listen 80;
server_name localhost jeson.t.imooc.io;
#charset koi8-r
access_log /var/log/nginx/test_proxy.access.log main;
location / {
proxy_pass http://imooc;
include proxy_params;
}
# error_page 404 /404.html
}
服務(wù)器在負(fù)載均衡調(diào)度中的狀態(tài):
- down:當(dāng)前的 Server 暫時(shí)不參與負(fù)載均衡
- backup:預(yù)留的備份服務(wù)器
- max_fails:允許請(qǐng)求失敗的次數(shù)
- fail_timeout:經(jīng)過max_fails 失敗后,服務(wù)暫停的時(shí)間
- max_conns:限制最大的接收的連接數(shù)






