1. lvs、nginx、HAProxy、keepalive工作原理
1.1. 前言
- 遇到了負載均衡和高可用選型問題,我覺的有必要好好理解下lvs,nginx,haproxy和keepalive的區別和聯系
- LVS、Nginx、HAProxy 是目前使用最廣泛的三種軟件負載均衡軟件。
- 一般對負載均衡的使用是隨着網站規模的提升根據不同的階段來使用不同的技術。具體的應用需求還得具體分析,如果是中小型的 Web 應用,比如日 PV 小於1000萬,用 Nginx 就完全可以了;如果機器不少,可以用 DNS 輪詢,LVS 所耗費的機器還是比較多的;大型網站或重要的服務,且服務器比較多時,可以考慮用 LVS。
- 目前比較流行的架構方案
- web前端采用nginx/HAProxy+Keepalived作為負載均衡
- 后端mysql數據庫一主多從和讀寫分離,采用lvs+keepalived的架構
1.2. 網絡分層架構


1.3. LVS
- LVS 是 Linux Virtual Server 的簡稱,也就是 Linux 虛擬服務器。
- 現在 LVS 已經是 Linux 標准內核的一部分,從 Linux2.4 內核以后,已經完全內置了 LVS 的各個功能模塊,無需給內核打任何補丁,可以直接使用 LVS 提供的各種功能。
1.3.1. LVS 負載均衡機制
- LVS是四層負載均衡,也就是傳輸層上,傳輸層有TCP/UDP,LVS 支持 TCP/UDP 的負載均衡。因為 LVS 是四層負載均衡,因此它相對於其它高層負載均衡的解決辦法,比如 DNS 域名輪流解析、應用層負載的調度、客戶端的調度等,它的效率是非常高的。
- 所謂四層負載均衡 ,也就是主要通過報文中的目標地址和端口。七層負載均衡 ,也稱為“內容交換”,也就是主要通過報文中的真正有意義的應用層內容。
- LVS 的轉發主要通過修改 IP 地址(NAT 模式,分為源地址修改 SNAT 和目標地址修改 DNAT)、修改目標 MAC(DR 模式)來實現。
1.3.2. LVS負載模式
1.3.2.1. NAT 模式:網絡地址轉換
- NAT(Network Address Translation)是一種外網和內網地址映射的技術。NAT 模式下,網絡數據報的進出都要經過 LVS 的處理。LVS 需要作為 RS(真實服務器)的網關。
- 當包到達 LVS 時,LVS 做目標地址轉換(DNAT),將目標 IP 改為 RS 的 IP。RS 接收到包以后,仿佛是客戶端直接發給它的一樣。RS 處理完,返回響應時,源 IP 是 RS IP,目標 IP 是客戶端的 IP。這時 RS 的包通過網關(LVS)中轉,LVS 會做源地址轉換(SNAT),將包的源地址改為 VIP,這樣,這個包對客戶端看起來就仿佛是 LVS 直接返回給它的。

1.3.2.2. DR 模式:直接路由
- DR 模式下需要 LVS 和 RS 集群綁定同一個 VIP(RS 通過將 VIP 綁定在 loopback 實現),但與 NAT 的不同點在於:請求由 LVS 接受,由真實提供服務的服務器(RealServer,RS)直接返回給用戶,返回的時候不經過 LVS。
- 詳細來看,一個請求過來時,LVS 只需要將網絡幀的 MAC 地址修改為某一台 RS 的 MAC,該包就會被轉發到相應的 RS 處理,注意此時的源 IP 和目標 IP 都沒變,LVS 只是做了一下移花接木。RS 收到 LVS 轉發來的包時,鏈路層發現 MAC 是自己的,到上面的網絡層,發現 IP 也是自己的,於是這個包被合法地接受,RS 感知不到前面有 LVS 的存在。而當 RS 返回響應時,只要直接向源 IP(即用戶的 IP)返回即可,不再經過 LVS。

- DR 負載均衡模式數據分發過程中不修改 IP 地址,只修改 mac 地址,由於實際處理請求的真實物理 IP 地址和數據請求目的 IP 地址一致,所以不需要通過負載均衡服務器進行地址轉換,可將響應數據包直接返回給用戶瀏覽器,避免負載均衡服務器網卡帶寬成為瓶頸。
1.3.2.3. IP隧道模式
- 隧道模式則類似於VPN的方式,使用網絡分層的原理,在從客戶端發來的數據包的基礎上,封裝一個新的IP頭標記(不完整的IP頭,只有目的IP部)發給RS,RS收到后,先把DR發過來的數據包的頭給解開,還原其數據包原樣,處理后,直接返回給客戶端,而不需要再經過DR。
1.3.2.4. 總結
- 因此,DR 模式具有較好的性能,也是目前大型網站使用最廣泛的一種負載均衡手段。
1.3.3. LVS已實現了以下八種調度算法:
1.3.3.1. LVS負載均衡算法---1.輪詢調度(Round-RobinScheduling)
- 調度器通過"輪詢"調度算法將外部請求按順序輪流分配到集群中的真實服務器上,它均等地對待每一台服務器,而不管服務器上實際的連接數和系統負載。
1.3.3.2. LVS負載均衡算法---2.加權輪詢調度(WeightedRound-RobinScheduling)
- 調度器通過"加權輪詢"調度算法根據真實服務器的不同處理能力來調度訪問請求。這樣可以保證處理能力強的服務器處理更多的訪問流量。調度器可以自動問詢真實服務器的負載情況,並動態地調整其權值。
1.3.3.3. LVS負載均衡算法---3.最小連接調度(Least-ConnectionScheduling)
- 調度器通過"最少連接"調度算法動態地將網絡請求調度到已建立的鏈接數最少的服務器上。如果集群系統的真實服務器具有相近的系統性能,采用"最小連接"調度算法可以較好地均衡負載。
1.3.3.4. LVS負載均衡算法---4.加權最小連接調度(WeightedLeast-ConnectionScheduling)
- 在集群系統中的服務器性能差異較大的情況下,調度器采用"加權最少鏈接"調度算法優化負載均衡性能,具有較高權值的服務器將承受較大比例的活動連接負載。調度器可以自動問詢真實服務器的負載情況,並動態地調整其權值
1.3.3.5. LVS負載均衡算法---5.基於局部性的最少鏈接(Locality-BasedLeastConnectionsScheduling)
- 基於局部性的最少鏈接"調度算法是針對目標IP地址的負載均衡,目前主要用於Cache集群系統。該算法根據請求的目標IP地址找出該目標IP地址最近使用的服務器,若該服務器是可用的且沒有超載,將請求發送到該服務器;若服務器不存在,或者該服務器超載且有服務器處於一半的工作負載,則用"最少鏈接"的原則選出一個可用的服務器,將請求發送到該服務器。
1.3.3.6. LVS負載均衡算法---6.帶復制的基於局部性最少鏈接(Locality-BasedLeastConnectionswithReplicationScheduling)
1.3.3.7. LVS負載均衡算法---7.目標地址散列調度(DestinationHashingScheduling)
- 目標地址散列"調度算法根據請求的目標IP地址,作為散列鍵(HashKey)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空
1.3.3.8. LVS負載均衡算法---8.源地址散列調度(SourceHashingScheduling)
- 源地址散列"調度算法根據請求的源IP地址,作為散列鍵(HashKey)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。
1.3.4. LVS 的優點
- 抗負載能力強、是工作在傳輸層上僅作分發之用,沒有流量的產生,這個特點也決定了它在負載均衡軟件里的性能最強的,對內存和 cpu 資源消耗比較低。
- 配置性比較低,這是一個缺點也是一個優點,因為沒有可太多配置的東西,所以並不需要太多接觸,大大減少了人為出錯的幾率。
- 工作穩定,因為其本身抗負載能力很強,自身有完整的雙機熱備方案,如 LVS+Keepalived。
- 無流量,LVS 只分發請求,而流量並不從它本身出去,這點保證了均衡器 IO 的性能不會受到大流量的影響。
- 應用范圍比較廣,因為 LVS 工作在傳輸層,所以它幾乎可以對所有應用做負載均衡,包括 http、數據庫、在線聊天室等等。
1.3.5. LVS 的缺點
- 軟件本身不支持正則表達式處理,不能做動靜分離;而現在許多網站在這方面都有較強的需求,這個是 Nginx、HAProxy+Keepalived 的優勢所在。
- 如果是網站應用比較龐大的話,LVS/DR+Keepalived 實施起來就比較復雜了,相對而言,Nginx/HAProxy+Keepalived就簡單多了
1.4. Nginx
- Nginx 是一個強大的 Web 服務器軟件,用於處理高並發的 HTTP 請求和作為反向代理服務器做負載均衡。具有高性能、輕量級、內存消耗少,強大的負載均衡能力等優勢。
1.4.1. Nignx 的架構設計
- 相對於傳統基於進程或線程的模型(Apache就采用這種模型)在處理並發連接時會為每一個連接建立一個單獨的進程或線程,且在網絡或者輸入/輸出操作時阻塞。這將導致內存和 CPU 的大量消耗,因為新起一個單獨的進程或線程需要准備新的運行時環境,包括堆和棧內存的分配,以及新的執行上下文,當然,這些也會導致多余的 CPU 開銷。最終,會由於過多的上下文切換而導致服務器性能變差。
- Nginx 的架構設計是采用模塊化的、基於事件驅動、異步、單線程且非阻塞。
- Nginx 大量使用多路復用和事件通知,Nginx 啟動以后,會在系統中以 daemon 的方式在后台運行,其中包括一個 master 進程,n(n>=1) 個 worker 進程。所有的進程都是單線程(即只有一個主線程)的,且進程間通信主要使用共享內存的方式。

1.4.2. Nginx 負載均衡
- Nginx 負載均衡主要是對七層網絡通信模型中的第七層應用層上的 http、https 進行支持。
- Nginx 是以反向代理的方式進行負載均衡的。反向代理(Reverse Proxy)方式是指以代理服務器來接受 Internet 上的連接請求,然后將請求轉發給內部網絡上的服務器,並將從服務器上得到的結果返回給 Internet 上請求連接的客戶端,此時代理服務器對外就表現為一個服務器。
- Nginx 實現負載均衡的分配策略有很多,Nginx 的 upstream 目前支持以下幾種方式:
- 輪詢(默認):每個請求按時間順序逐一分配到不同的后端服務器,如果后端服務器 down 掉,能自動剔除。
- weight:指定輪詢幾率,weight 和訪問比率成正比,用於后端服務器性能不均的情況。
- ip_hash:每個請求按訪問 ip 的 hash 結果分配,這樣每個訪客固定訪問一個后端服務器,可以解決 session 的問題。
- fair(第三方):按后端服務器的響應時間來分配請求,響應時間短的優先分配。
- url_hash(第三方):按訪問 url 的 hash 結果來分配請求,使每個 url 定向到同一個后端服務器,后端服務器為緩存時比較有效。
1.4.3. Nginx 的優點
- 跨平台:Nginx 可以在大多數 Unix like OS編譯運行,而且也有 Windows 的移植版本配置異常簡單:非常容易上手。配置風格跟程序開發一樣,神一般的配置
- 非阻塞、高並發連接:官方測試能夠支撐5萬並發連接,在實際生產環境中跑到2~3萬並發連接數
- 事件驅動:通信機制采用 epoll 模型,支持更大的並發連接
- Master/Worker 結構:一個 master 進程,生成一個或多個 worker 進程
- 內存消耗小:處理大並發的請求內存消耗非常小。在3萬並發連接下,開啟的10個 Nginx 進程才消耗150M 內存(15M*10=150M)
- 內置的健康檢查功能:如果 Nginx 代理的后端的某台 Web 服務器宕機了,不會影響前端訪問
- 節省帶寬:支持 GZIP 壓縮,可以添加瀏覽器本地緩存的 Header 頭
- 穩定性高:用於反向代理,宕機的概率微乎其微
1.4.4. Nginx 的缺點
- Nginx 僅能支持http、https 和 Email 協議,這樣就在適用范圍上面小些,這個是它的缺點
- 對后端服務器的健康檢查,只支持通過端口來檢測,不支持通過url來檢測。不支持 Session 的直接保持,但能通過 ip_hash 來解決
1.5. HAProxy
- HAProxy 支持兩種代理模式 TCP(四層)和HTTP(七層),也是支持虛擬主機的
- HAProxy 的優點能夠補充 Nginx 的一些缺點,比如支持 Session 的保持,Cookie 的引導;同時支持通過獲取指定的 url 來檢測后端服務器的狀態。
- HAProxy 跟 LVS 類似,本身就只是一款負載均衡軟件;單純從效率上來講 HAProxy 會比 Nginx 有更出色的負載均衡速度,在並發處理上也是優於 Nginx 的。
- HAProxy 支持 TCP 協議的負載均衡轉發,可以對 MySQL 讀進行負載均衡,對后端的 MySQL 節點進行檢測和負載均衡,大家可以用 LVS+Keepalived 對 MySQL 主從做負載均衡。
- HAProxy 負載均衡策略非常多:Round-robin(輪循)、Weight-round-robin(帶權輪循)、source(原地址保持)、RI(請求URL)、rdp-cookie(根據cookie)。
1.6. 什么是keepalived
- keepalived是保證集群高可用的一個服務軟件,其功能類似於heartbeat,用來防止單點故障。
- 以VRRP協議為實現基礎的,VRRP全稱Virtual Router Redundancy Protocol,即虛擬路由冗余協議。
- keepalived是可以工作在第三層、第四層、第五層的檢測服務器狀態的軟件
- 如果有一台web服務器死機,或工作出現故障,keepalived將檢測到,並將其從系統中剔除;當web服務器工作正常后keepalived自動將web服務器加入到服務器集群中
1.6.1. Keepalived的工作原理
- 三層、四層、五層工作在TCP/IP協議棧的IP層、TCP層、應用層。原理如下:
- 三層:keepalived使用三層方式工作是,keepalived會定期向服務器集群中的服務器發送一個IMCP的數據包,也就是ping程序,如果發現某台服務器的IP地址沒有激活,keepalived便報告這台服務器失效,並將它從集群中刪除,這種情況的典型例子是某台服務器被非法關機。三層的方式是以服務器的IP地址是否有效作為服務器工作正常與否的標准。
- 四層:主要是以TCP端口的狀態來決定服務器工作正常與否。如web服務器的端口一般是80,如果keepalived檢測到80端口沒有啟動,則keepalived將這台服務器從集群中剔除。
- 五層:應用層,比三層和四層要復雜一點,keepalived將根據用戶的設定檢查服務器程序運行是否正常,如果與用戶設定的不相符,則keepalived將把服務器從服務器集群中剔除。
- 基於VRRP虛擬路由冗余協議,可以認為是實現路由器高可用的協議,即將N台提供相同功能的路由器組成一個路由器組,這個組里面有一個master和多個backup,master上面有一個對外提供服務的vip(該路由器所在局域網內其他機器的默認路由為該vip),master會發組播,當backup收不到vrrp包時就認為master宕掉了,這時就需要根據VRRP的優先級來選舉一個backup當master。這樣的話就可以保證路由器的高可用了。
- keepalived主要有三個模塊,分別是core、check和vrrp。core模塊為keepalived的核心,負責主進程的啟動、維護以及全局配置文件的加載和解析。check負責健康檢查,包括常見的各種檢查方式。vrrp模塊是來實現VRRP協議的。
1.6.2. keepalived的作用
- 高可用-可持續的服務器質量
- 負載均衡-橫向擴展
- 實現對失效服務器的隔離-通過健康監測,保證服務的可用性
- 實現:vrrp協議實現。(冗余網關路由協議)
1.6.3. keepalived體系結構

- watchdog 負責監控checkers和vrrp進程的狀況。
- Checkers 負責真實服務器的健康監測,是keepalived最主要的功能,換一句話說,可以沒有vrrp statck,但是健康檢查healthcheckping一定要有。
- Vrrp statck 負責負載均衡器之間失敗切換failover。如果只用一個負載均衡器,則vrrp不是必須的。
- Ipvs warpper是用來發送設定的規則封裝到內核ipvs代碼。
- Netlink reflector 用來設定vrrp的vip地址等。
- Keepalived功能十分強大,但是配置工作十分簡單,keepalived各種功能的實現是通過設定配置文件keepalived.conf來完成的。
參考: https://www.jianshu.com/p/16e9c84fdb3c