一、 什麼是負載均衡?
什麼是負載均衡?
記得第一次接觸 Nginx 是在實驗室,那時候在伺服器部署網站需要用 Nginx 。Nginx 是一個服務元件,用來反向代理、負載平衡和 HTTP 緩存等。那麼這裡的 負載均衡 是什麼?
負載均衡(LB,Load Balance),是一種技術解決方案。用來在多個資源(一般是伺服器)中配置設定負載,達到最優化資源使用,避免過載。

資源,相當于每個服務執行個體的執行操作單元,負載均衡就是将大量的資料處理操作分攤到多個操作單元進行執行,用來解決網際網路分布式系統的大流量、高并發和高可用的問題。那什麼是高可用呢?
二、什麼是高可用?
首先了解什麼是高可用?
這是 CAP 定理是分布式系統的基礎,也是分布式系統的 3 個名額:
- Consistency(一緻性)
- Availability(可用性)
- Partition tolerance(分區容錯性)
那高可用(High Availability)是什麼?高可用,簡稱 HA,是系統一種特征或者名額,通常是指,提供一定性能上的服務運作時間,高于平均正常時間段。反之,消除系統服務不可用的時間。
衡量系統是否滿足高可用,就是當一台或者多台伺服器當機的時候,系統整體和服務依然正常可用。
舉個例子,一些知名的網站保證 4 個 9 以上的可用性,也就是可用性超過 99.99%。那 0.01% 就是所謂故障時間的百分比。比如電商網站有贊,服務不可用會造成商家損失金錢和使用者。那麼在提高可用性基礎上同時,對系統當機和服務不可用會有補償。
比如下單服務,可以使用帶有負載均衡的多個下單服務執行個體,代替單一的下單服務執行個體,即使用備援的方式來提高可靠性。
總而言之,負載均衡(Load Balance)是分布式系統架構設計中必須考慮的因素之一。一般通過負載均衡,備援同一個服務執行個體的方式,解決分布式系統的大流量、高并發和高可用的問題。負載均衡核心關鍵:在于是否配置設定均勻。
三、常見的負載均衡案例
場景1:微服務架構中,網關路由到具體的服務執行個體 hello:
- 兩個相同的服務執行個體 hello service ,一個端口 8000 ,另一個端口 8082
- 通過 Kong 的負載均衡 LB 功能,讓請求均勻的分發到兩個 hello 服務執行個體
- Kong 的負載均衡政策算法很多:預設 weighted-round-robin 算法,還有 consumer: consumer id 作為 hash 算法輸入值等
場景2:微服務架構中,A 服務調用 B 服務的叢集。通過了 Ribbon 用戶端負載均衡元件:
- 負載均衡政策算法并不進階,最簡單的是随機選擇和輪循
四、網際網路分布式系統解決方案
常見的網際網路分布式系統架構分為幾層,一般如下:
- 用戶端層:比如使用者浏覽器、APP 端
- 反向代理層:技術選型 Nignx 或者 F5 等
- Web 層:前後端分離場景下, Web 端可以用 NodeJS 、 RN 、Vue
- 業務服務層:用 Java 、Go,一般網際網路公司,技術方案選型就是 SC 或者 Spring Boot + Dubbo 服務化
- 資料存儲層:DB 選型 MySQL ,Cache 選型 Redis ,搜尋選型 ES 等
一個請求從第 1 層到第 4 層,層層通路都需要負載均衡。即每個上遊調用下遊多個業務方的時候,需要均勻調用。這樣整體系統來看,就比較負載均衡
第 1 層:用戶端層 -> 反向代理層 的負載均衡
用戶端層 -> 反向代理層的負載均衡如何實作呢?
答案是:DNS 的輪詢。DNS 可以通過 A (Address,傳回域名指向的 IP 位址)設定多個 IP 位址。比如這裡通路 bysocket.com 的 DNS 配置了 ip1 和 ip2 。為了反向代理層的高可用,至少會有兩條 A 記錄。這樣備援的兩個 ip 對應的 nginx 服務執行個體,防止單點故障。
每次請求 bysocket.com 域名的時候,通過 DNS 輪詢,傳回對應的 ip 位址,每個 ip 對應的反向代理層的服務執行個體,也就是 nginx 的外網ip。這樣可以做到每一個反向代理層執行個體得到的請求配置設定是均衡的。
第 2 層:反向代理層 -> Web 層 的負載均衡
反向代理層 -> Web 層 的負載均衡如何實作呢?
是通過反向代理層的負載均衡子產品處理。比如 nginx 有多種均衡方法:
1. 請求輪詢。請求按時間順序,逐一配置設定到 web 層服務,然後周而複始。如果 web 層服務 down 掉,自動剔除
upstream web-server {
server ip3;
server ip4;
}
複制
2. ip 哈希。按照 ip 的哈希值,确定路由到對應的 web 層。隻要是使用者的 ip 是均勻的,那麼請求到 Web 層也是均勻的。還有個好處就是同一個 ip 的請求會分發到相同的 web 層服務。這樣每個使用者固定通路一個 web 層服務,可以解決 session 的問題。
upstream web-server {
ip_hash;
server ip3;
server ip4;
}
複制
3. weight 權重 、 fair、url_hash 等
第 3 層:Web 層 -> 業務服務層 的負載均衡
Web 層 -> 業務服務層 的負載均衡如何實作呢?
比如 Dubbo 是一個服務治理方案,包括服務注冊、服務降級、通路控制、動态配置路由規則、權重調節、負載均衡。其中一個特性就是智能負載均衡:内置多種負載均衡政策,智能感覺下遊節點健康狀況,顯著減少調用延遲,提高系統吞吐量。
為了避免避免單點故障和支援服務的橫向擴容,一個服務通常會部署多個執行個體,即 Dubbo 叢集部署。會将多個服務執行個體成為一個服務提供方,然後根據配置的随機負載均衡政策,在20個 Provider 中随機選擇了一個來調用,假設随機到了第7個 Provider。LoadBalance 元件從提供者位址清單中,使用均衡政策,選擇選一個提供者進行調用,如果調用失敗,再選另一台調用。
Dubbo内置了4種負載均衡政策:
- RandomLoadBalance:随機負載均衡。随機的選擇一個。是Dubbo的預設負載均衡政策。
- RoundRobinLoadBalance:輪詢負載均衡。輪詢選擇一個。
- LeastActiveLoadBalance:最少活躍調用數,相同活躍數的随機。活躍數指調用前後計數差。使慢的 Provider 收到更少請求,因為越慢的 Provider 的調用前後計數差會越大。
- ConsistentHashLoadBalance:一緻性哈希負載均衡。相同參數的請求總是落在同一台機器上。
同樣,因為業務的需要,也可以實作自己的負載均衡政策
第 4 層:業務服務層 -> 資料存儲層 的負載均衡
資料存儲層的負載均衡,一般通過 DBProxy 實作。比如 MySQL 分庫分表。
當單庫或者單表通路太大,資料量太大的情況下,需要進行垂直拆分和水準拆分兩個次元。比如水準切分規則:
- Range 、 時間
- hash 取模,訂單根據店鋪ID 等
但伴随着這塊的負載會出現下面的問題,需要解決:
- 分布式事務
- 跨庫 join 等
現狀分庫分表的産品方案很多:當當 sharding-jdbc、阿裡的 Cobar 等
五、小結
對外看來,負載均衡是一個系統或軟體的整體。對内看來,層層上下遊調用。隻要存在調用,就需要考慮負載均衡這個因素。是以負載均衡(Load Balance)是分布式系統架構設計中必須考慮的因素之一。考慮主要是如何讓下遊接收到的請求是均勻分布的:
- 第 1 層:用戶端層 -> 反向代理層 的負載均衡。通過 DNS 輪詢
- 第 2 層:反向代理層 -> Web 層 的負載均衡。通過 Nginx 的負載均衡子產品
- 第 3 層:Web 層 -> 業務服務層 的負載均衡。通過服務治理架構的負載均衡子產品
- 第 4 層:業務服務層 -> 資料存儲層 的負載均衡。通過資料的水準分布,資料均勻了,理論上請求也會均勻。比如通過買家ID分片類似
參考資料:
- 《關于負載均衡的一切》
- 《Dubbo 的負載均衡》http://dubbo.apache.org/zh-cn/blog/dubbo-loadbalance.html
- https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1