Nginx,為什么依舊這么“香”?
Nginx 很好用,幾乎每個公司都在用,它的功能主要有反向代理、 負載均衡、 動靜分離等,其中最主要的就是反向代理。
圖片來自 Pexels
它的主要架構圖如下:
客戶端是無法直接訪問后端的 Server 的,因為 Server 資源高高在上,Client 并沒有權限。
這個時候,就需要有一個 Proxy,進行代理,將客戶端的請求進行轉發,然后把結果返回給 Client。
為什么不能直接讓 Client 訪問 Server 呢?這就涉及到資源隔離問題。Server 的一些真實意圖,是不想要 Client 知曉的,比如一些受安全保護的敏感資源。
也就是說,通過 Proxy,Server 想讓 Client 看到啥,Client 也只能看到啥。對 Client 來說,功能總是閹割的!甚至是篡改的!
我們將圖中的元素替換一下,奇妙的事情發生了。
我們把 Client 換成可憐的普通碼農,把 Server 換成牛 X 的領導,可以看到 6 條綠色的箭頭,帶著呼嘯的山風,無情的指向了 Proxy。
Proxy 成為了關鍵的資源。這個 Proxy 要求可不簡單,需要五弊三缺,上承天命,下召九幽。這么牛 X 的存在,當之無愧稱之為 Nginx 工程師。
Nginx 工程師不需要有自己的想法,但他必須記住領導的每一句話,領會領導的真實意圖。
傳導領導想法的時候,也知道輕重,知道過濾,能夠快狠準的將領導的想法廣播出去。不服不行,這還真不是一般人能做的。
哪些人能夠成為 Nginx 工程師呢?在奴隸社會,無論一個奴隸(Slave)工作多么的賣力,能力多么的出眾,都沒有出頭之日。
反而是那些拿著鞭子的監工們,更容易獲得主人們的贊賞,喝酒吃肉的時候都能夠想到他們。
更加奇妙的是,如果把監工們和奴隸們的工作調換一下。奴隸有可能會勝任監工的工作,而監工絕無可能勝任奴隸的工作。
這是為什么呢?總結下來可以有這么幾點:
- 監工知道更多的內幕資源,更容易投主人所好。
- 監工的工作屬性是管理,可操作空間大。
- 監工離權利中心更近,耳邊風吹的頻率要高一些。
你可能會說,這是社會性質使然,現在的社會肯定沒這問題。你答對了一半,問題就出在這里。
由于每個公司的進化程度不一,程序員在不同的公司,獲得的感受和受到的待遇,也是非常大的。你甚至會產生圖中爸爸的心態。
監工一般都不是一線,離生產是比較遠的,對于 Client 的想法,只能領會一點點。這一點點傳導到 Server 那里的,正確性更難以保證。
而且,監工由于領會領導意圖和匯總 Excel,耗費了大量的精力,花在真正有意義的事上的時間,就少的可憐。那怎么辦呢?只好拿 Client 的成果當作自己的成果。
所以,悶頭寫代碼的程序員,可能會發現自己做了很多工作,經過 Proxy 的一加工一轉達,到了領導那里就是個屁。
Proxy 做的沒錯,996 的 Client 深夜也需要調代碼,Proxy 只需要在一旁刷 TikTok 就可以了。工作強度不一樣,工時自然就沒有衡量對比的價值。
我們可以再看 Proxy 的 3 種傳導場景。
場景 1:
- server:要加強員工文化建設。
- proxy:周六、周末去團建,AA
- client: WCNM
場景 2:
- server:公司要勤儉節約。
- proxy:從明天開始不提供廁紙和開水
- client: WCNM
場景 3:
- server:王xx同學拼搏奮斗,是公司的楷模。
- proxy:開啟狼性文化,明起996
- client: WCNM
可以看到,這一層的 Proxy 素質尤其重要。如果你不巧碰見了一個水貨 Proxy,你的悲慘程度可想而知。
但如果你遇到一個 Nice 的 Proxy,那就珍惜他,因為所有的壓力,都需要由他傳導。
那一般的 Nginx 工程師是怎么做的呢?為了讓驢拉磨,人們想出四招:蒙眼睛、捂嘴巴、堵耳朵、抽鞭子。
同樣,要想 Proxy 順利推行,Proxy 就可以不讓你看到某些事情;你想要發表意見的時候,使用暴力手段堵住你的嘴;當你想要聆聽領導真實意圖,堵住你的耳朵;當你有所懈怠的時候,使用鞭子督促你完成工作。
很多公司由于人員眾多,結構復雜,就存在著多層 Proxy 的拓撲。這種公司非常的精彩,一個 Proxy,可以作為另一個 Proxy 的 Client,很多時候,竟然會發生 Server 的數量比 Client 的數量多的情況。
我很可憐這些 Proxy 們,他們活的太累了。但由于 Proxy 的工作特性,只需要進行完整的轉發即可完成工作,不需要思考--自然有一頭烏黑油亮的秀發。
加上 Nginx 工程師可以很容易打破 35 歲魔咒,所以這個職業依然讓人趨之若鶩。你也想做一枚 Nginx 工程師么?
如何保證 Nginx 的高可用?
目前 HTTP 協議,乃至 WebSocket 協議,乃至采用了 MQTT 協議的 WebSocket 協議,都不可避免的使用了 Nginx。
所謂病從口入,禍從口出。作為入口,Nginx 承擔的責任非常的重要。假如某個時刻不能用了,那可真是災難。
如何保證 Nginx 的高可用呢?這是個問題。不論你用什么樣的方案,到最后總是要歸為單一,很讓人苦惱。
所謂的高可用,無非兩種方式:
- 一種方式就是在組件自身上做文章。
- 另外一種方式,就是加入一個中間層。
我們通常希望在高可用的時候,同時還能夠負載均衡,典型的貓和狗都想要,貪婪的很。
每當解決不了問題的時候,我們都會加入一個中間層,然后把希望寄托在這個新生的組件上。
如果這個中間層解決不了問題,我們就可以加入另外一個中間層。就這樣一層套一層,到最后系統高可用架構就會變得非常復雜。
DNS 保證高可用
第一種方式當然是要在 DNS 上做文章了。通過在 DNS 上,綁定多個 Nginx 的 IP 地址,即可完成高可用。不僅能夠完成高可用,還能順便完成負載均衡。
但這玩意有一個致命的問題,那就是故障的感知時間。
我們的瀏覽器在訪問到真正的 Nginx 之前,需要把域名轉化為真正的 IP 地址,DNS 就是干解析這個動作的,每次需要耗費 20-20ms 不等。
為了加快解析速度,一般都會有多級的緩存。比如瀏覽器就有 DNS 的緩存;你使用的 PC 機上也有這樣的緩存;IPS 服務提供商,也會有緩存;再加上有的企業為了加速訪問所自建的 DNS 服務器,中間的緩存層就更多了。
只有所有的緩存都不命中的情況下,DNS 才會查詢真正的 IP 地址。所以,如果有一臺 Nginx 宕機了,這個故障的感知能力就會特別的差。總有一部分用戶的請求,會落在這臺已經死亡的機器上。
硬件保證高可用
我們前面說了。解決不了的問題,就可以加中間層,即使這個中間層是硬件,比如 F5。
這種架構一般的企業玩不起,只有那些采購有回扣有油水的公司,才會喜歡這個。互聯網中用的很少,就不過多介紹了。
當然,F5 同樣有單點的問題。雖然硬件肯定要比軟件穩定上一點,但是總歸是一個隱患。
就像 Oracle 無論再厲害,它還是有出問題的時候,到時候備機是必須的。有的廠商在賣硬件的時候,推薦你一次買 3 個!為啥呢?這也有理由。
你的一臺硬件正在服務,有兩臺備份機器。當你服務的這臺機器出現問題時,就可以選取備份機中的其中一臺作為主機,另一臺依然是備機,集群還是高可用的。
這理由真讓人陶醉。按照這個邏輯,碰到傻子,我可以賣出 100 臺!
①主備模式
硬的不行,就要來軟的。采用主備的模式,使用軟件來完成切換過程。
如圖,使用 Keepalived 組件,通過 VRRP 協議,即可完成最簡單的高可用配置。
我們把 DNS 的地址綁定在 VIP 上,當正在服務的 Nginx 發生問題,VIP 會發生漂移,轉移到另外一臺 Nginx 上。
可以看到,備份的 Nginx,正常情況下是無法進行服務的,它也叫做影子節點,只有主 Nginx 發生問題的時候才有用。如果你的節點非常多,這種模式下,會有非常大的浪費。
除了浪費,還有一個非常大的問題。那就是,單臺 Nginx 無論性能多么牛 X,總是有上限的。當網卡的流量達到頂峰,接下來何去何從呢?
這種模式肯定是不滿足需求的。
②簡單組合模式
這個時候,我們就可以配合 DNS 解析,以及主備模式做文章了。如下圖,DNS 解析到兩個 VIP 上,VIP 本身也做了高可用。
這樣就能夠縮短故障時間,同時也能夠保證每個組件的高可用。
這種架構模式思路是非常清晰的,但依然存在影子節點的浪費。
③LVS+KeepAlived+Nginx
LVS 是 Linux Virtual Server 的簡稱,也就是 Linux 虛擬服務器。
現在 LVS 已經是 Linux 標準內核的一部分,從 Linux2.4 內核以后,已經完全內置了 LVS 的各個功能模塊,無需給內核打任何補丁,可以直接使用 LVS 提供的各種功能。
LVS 工作在 OSI 模型的第四層:傳輸層,比如 TCP/UDP,所以像七層網絡的 HTTP 協議,它是識別不出來的。
也就是說,我們不能拿 HTTP 協議的一些內容來控制路由,它的路由切入層次更低一些。
如下圖,LVS 架設的服務器集群系統有三個部分組成:
- 最前端的負載均衡層,用 Load Balancer 表示。
- 中間的服務器集群層,用 Server Array 表示。
- 最底端的數據共享存儲層,用 Shared Storage 表示。
DR(直接路由)模式可將響應數據包直接返回給用戶瀏覽器,避免負載均衡服務器網卡帶寬成為瓶頸,是目前采用最為廣泛的方式(數據不詳,Fullnat 模式使用也比較廣泛)。
所以,配合 DNS 的負載均衡,加上 LVS 的負載均衡,可以實現雙層的負載均衡和高可用。
如圖,DNS 可以將請求綁定在 VIP 上。由于 LVS DR 模式的效率非常高,網卡要達到瓶頸也需要非常大的請求量(只有入口流量才走 LVS),所以一般通過 LVS 做 Nginx 的負載均衡就足夠了。
如果 LVS 還有瓶頸,那么就可以在 DNS 上再做文章。
還有哪些挑戰?其實,我們上面談到的這些方案,大多數是在同機房的。如果在多個機房,如何讓用戶選擇最快的節點、如何保證負載均衡,又是一個大的問題。
另外,你可以看到數據包經過層層的轉發和協調,還有多種負載均衡算法參與其中,如何保持會話,也是一個挑戰。
一般的,四層會話會通過 IP 地址去實現,七層會話會通過 Cookie 或者頭信息等去實現。
開發人員一般情況下接觸不到這么入口級的東西,但一旦遇到了,可能會受忙腳亂。
本文是我根據一些即有的經驗進行整理,希望你在公司需要一些高可用方案的時候,能夠助你一臂之力。
PS:什么叫方案?你只需要當時把你的領導哄好,讓他感覺很認同的樣子就行了。至于要不要做,具體怎么做,那都是后面的事。
君不見,扯了這么半天,很多企業其實一個 Nginx,就可以走天下。
作者:小姐姐味道
簡介:聚焦基礎架構和 Linux。十年架構,日百億流量,與你探討高并發世界,給你不一樣的味道。
編輯:陶家龍
出處:轉載自公眾號小姐姐味道(ID:xjjdog)