文章目錄
- What and Why
- 七層負載均衡Nginx
- 初入江湖:加一層Nginx
- 小試牛刀:動靜分離CDN
- 瓶頸分析:socket連接池
- 四層負載均衡LVS
- LVS的作業原理 之 NAT,網路地址轉換
- LVS的作業原理 之 DR(Direct Router,直接路由)、
- 解決NAT模式下的單點問題FullNAT
What and Why
負載均衡和反向代理其實是非常融合的概念,在后端的設計,為了提高系統的可用性,我們往往會使用多個服務器實體給 client 提供服務,但是這些對于客戶端是不應該有感知的,也就是說客戶端在發送請求的時候,是通過一個網址,網址在進行DNS的決議以后會被發送到一個固定的IP地址上(先不考慮DNS的路由選擇),
反向代理的目的就是接受 client發送過來的請求,并將請求轉發到配置到的多個路由實體上,轉發的規則就是負載均衡演算法,
七層負載均衡Nginx
初入江湖:加一層Nginx
沒有什么是加一層解決不了的,在我們的網路層之前,我們可以加一層Nginx進行代理和轉發,Nginx的性能本身還是非常好的,因為使用了master-worker設計,epoll的IO,以及協程機制,當然這些不是本文的討論重點,當然一般為了安全,實際在流量打到 server 前再做一層鑒權操作,鑒權通過了我們才讓它打到 server 上,我們把這一層叫做網關,

小試牛刀:動靜分離CDN
在實際的后端業務種,可以將請求分為動態請求(需要去資料庫中查詢或者執行邏輯)和靜態請求(如 js,css檔案),不管是動態請求,還是靜態資源請求都打到 tomcat 了,這樣在流量大時會造成 tomcat 承受極大的壓力,其實對于靜態資源的處理 tomcat 不如 Nginx,tomcat 每次都要從磁盤加載檔案比較影響性能,而 Nginx 有 proxy cache 等功能可以極大提升對靜態資源的處理能力,
當然對于靜態資源最好的方案就是存放在CDN上,還可以考慮地理上的就近接入,
同時也需要避免一些單點問題,比如我們前面的Nginx是一個典型的單點,我們可以部署兩臺Nginx,以主備的形式存在,備 Nginx 會通過 keepalived 機制(發送心跳包) 來及時感知到主 Nginx 的存活,發現宕機自己就頂上充當主 Nginx 的角色,

瓶頸分析:socket連接池
看起來這樣的架構確實不錯,但要注意的是 Nginx 是七層(即應用層)負載均衡器 ,這意味著如果它要轉發流量首先得和 client 建立一個 TCP 連接,并且轉發的時候也要與轉發到的上游 server 建立一個 TCP 連接,而我們知道建立 TCP 連接其實是需要耗費記憶體(TCP Socket,接收/發送快取區等需要占用記憶體)的,客戶端和上游服務器要發送資料都需要先發送暫存到到 Nginx 再經由另一端的 TCP 連接傳給對方,
因此在 Nginx 的負載能力受限于機器I/O,CPU記憶體等一系列配置,一旦連接很多(比如達到百萬)的話,Nginx 抗負載能力就會急劇下降,
通過對問題的分析我們可以看出,Nginx的強大之處在于非常豐富的整合,自己做到的了反向代理、負載均衡、提供了快取靜態資源的shared dict、lua腳本等,但是在高流量的壓力下,這種豐富的整合反而成為了軟肋,我們希望有一個功能更為單一,性能更強大的選擇,
四層負載均衡LVS
我們希望有一個類似Nginx的路由器,但是只負責轉發包,不需要真正的建立連接,這樣就不需要維護額外的TCP連接,
LVS在接收到第一個來自客戶端的SYN 請求時,即通過負載均衡演算法選擇一個最佳的服務器,并對報文中目標IP地址進行修改(改為后端服務器 IP ),直接轉發給該服務器,TCP 的連接建立,即三次握手是客戶端和服務器直接建立的,負載均衡設備只是起到一個類似路由器的轉發動作,在某些部署情況下,為保證服務器回包可以正確回傳給負載均衡設備,在轉發報文的同時可能還會對報文原來的源地址進行修改,
我們在 Nginx 上再加了一層 LVS,以讓它來承接我們的所有流量,當然為了保證 LVS 的可用性,我們也采用主備的方式部署 LVS,另外采用這種架構如果 Nginx 容量不夠我們可以很方便地進行水平擴容,于是我們的架構改進如下:

LVS的作業原理 之 NAT,網路地址轉換
我們可以想象一個網路資料包,由源IP,目的IP,源埠,目的埠組成了TCP四元組,可以唯一的確認一條鏈接,

首先調度器(LB)接收到客戶的請求資料包時(請求的目的IP為VIP、對外公網IP),根據調度演算法決定將請求發送給哪個后端的真實服務器(RS),然后調度就把客戶端發送的請求資料包的目標IP地址及埠改成后端真實服務器的IP地址(RIP),這樣真實服務器(RS)就能夠接收到客戶的請求資料包了,
真實服務器回應完請求后,查看默認路由(NAT模式下我們需要把RS的默認路由設定為LB服務器,)把回應后的資料包發送給LB,LB再接收到回應包后,把包的**源地址改成對外地址(VIP)**然后發送回給客戶端,
LVS 只是起到了修改 IP 地址并且轉發資料包的功能而已,由于它在資料包的進出程序中都修改了 IP 地址,我們稱這模式為 NAT(Network Address Translation,網路地址轉換) 模式,可以看到這種作業模式下,網路請求包和網路回應包都要經過 LVS,
- 缺點:性能問題,因為所有資料包的進出都要經過它,這讓它成為了很大的瓶頸,隨著 RS 水平擴展數量越來越多, LVS 遲早要掛掉,
LVS的作業原理 之 DR(Direct Router,直接路由)、
這個方案的核心思路在于:
首先 LVS 還是要承載所有的請求流量(接收所有資料包),然后再根據負載均衡演算法轉發給 RS
RS 處理完后是不經過 LVS,直接將資料包轉發給路由器再發給客戶端的,意味著 RS 必須要有與 LVS 同樣的 VIP(四元組不能變),另外由以上拓撲圖可知,它們也必須在同一個子網里(嚴格地說,應該是同一個 vlan,因為是通過交換機通信的),這就意味著 LVS 和 RS 都必須要有兩個 IP,一個 VIP,一個子網 IP
為了實作這兩種網卡,需要使用到物理網卡eth和虛擬網卡lo,標記紅色的IP地址為VIP,

arp_ignore = 1
首先我們知道 LVS 和 RS 都位于同一個子網,子網一般稱為以太網,主要用 mac 地址來通信,位于 ISO 模型的二層,一開始內網的機器互相不知道彼此的 mac 地址,需要通過 arp 機制來根據 IP 獲取其對應的 mac,獲取之后首先會在本地的 arp 表記錄此 IP 對應的 mac(下次就直接在本地快取查找 mac),然后會在包頭上附上 IP 對應的 mac,再將包傳輸出去,交換機就會找到對應的機器了,
所以當客戶端請求 VIP 后,請求到達了上圖中的路由器,路由器要轉發給此 IP 對應的機器,于是它首先發起了一個 arp 請求希望拿到 VIP 對應的 mac 地址,
由于請求都要經過 LVS,所以只讓 LVS 回應 arp,抑制住另外兩臺 RS 對 VIP 的 arp 回應即可,不過請求到達 LVS 后,LVS 還要將包轉發給 RS(假設為 RS2 吧),此時也要用到 arp 來獲取 RS 的 mac 地址,但是注意從 LVS 發起的 arp 請求目的 IP 變成了 RS2 的內網 IP:115.205.4.217(系結在物理網卡 eth0 上),
綜上所述, RS 不能回應目的 IP 為虛擬網卡系結的 VIP 的 arp 請求,但能回應目的 IP 為物理網卡系結的 IP 的 arp 請求,這就是為什么 RS 需要把 VIP 系結在虛擬網卡上,而把內網 IP 系結在物理網卡上的真實原因,就是為了 arp 回應的需要,
通過對RS配置arp_ignore = 1,實作只回應目的 IP 為接收網卡(即物理網卡)上的 IP 的 arp 請求(會忽略目的 IP 為虛擬網卡 上 VIP 的 arp 請求),并且需要讓資料包使用 lo 介面發送
在使用了以上設定以后,所有的請求通過APR決議都會達到LVS上,然后LVS將資料包發送給RS2;RS2在處理完以后將資料包通過lo網口發出,
arp_announce=2
在RS將資料包發送給網關的程序中,同樣需要一次ARP尋找到對應的網關的mac地址,而在ARP協議中需要添加上自己的IP和mac地址的,這里對于RS并不能正常的填寫上自己發送請的lo地址(這個RS的lo地址和LVS的eth地址是一眼給的),否則網卡會更新ARP快取導致之后的請求無法被正確的路由到LVS上,所以 RS2 要發 arp 獲取網關的 mac 時使用的源 IP 應該為其物理網卡(eth0)對應的 IP(即 115.205.4.217),
在DR模式下,需要配置arp_announce=2表示的是忽略 IP 資料包的源 IP 地址,選擇該發送網卡上最合適的本地地址作為 arp 請求的源 IP 地址
解決NAT模式下的單點問題FullNAT
NAT 的基礎上又衍生出了 FullNAT,FullNAT 其實就是為了公有云而生的,

NAT 模式下,LVS 只將資料包的目標 IP 改成了 RS 的 IP,而在 FullNAT 模式下,LVS 還會將源 IP 地址也改為 LVS 的內網 IP(修改 IP 主要由 LVS 的內核模塊 ip_vs 來操作),注意上圖 LVS 內網 IP 和 RS 的 IP 是可以在不同網段下的,通常在公有云平臺上,它們是部署在 intranet 即企業內網中的,這樣的話 LVS 就可以跨網段和 RS 通信了,也避免了 LVS 的單點瓶頸,多臺 LVS 都可以將請求轉發給 RS
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/307203.html
標籤:其他
上一篇:正向代理、反向代理和負載均衡
