RabbitMQ負載均衡(1)
面對大量業務訪問、高併發請求可以使用高效能的伺服器來提升RabbitMQ服務的負載能力。當單機容量達到極限時,我們可以採取叢集的策略來對負載能力做進一步的提升,但是這裡還存在一個負載不均衡的問題。試想如果一個叢集中有3個節點,那麼所有的客戶端都與其中的單個節點node1建立TCP連線,那麼node1的網路負載必然會大大增加而顯得難以承受,其他節點又由於沒有那麼多的負載而造成硬體資源的浪費,所以負載均衡顯得尤為重要。
負載均衡(Load balance)是一種計算機網路技術,用於在多個計算機(計算機叢集)、網路連線、CPU、磁碟驅動器或其他資源中分配負載,以達到最佳資源使用、最大化吞吐率、最小響應時間以及避免過載的目的。使用帶有負載均衡的多個伺服器元件,取代單一的元件,可以通過冗餘提高可靠性。負載均衡通常分為軟體負載均衡和硬體負載均衡兩種。
軟體負載均衡是指在一個或者多個互動的網路系統中的多臺放伺服器上安裝一個或多個相應的負載均衡軟體來實現一種均衡負載技術。軟體可以很方便的安裝在伺服器上,並且實現一定的均衡負載功能。軟體負載均衡技術配置簡單、操作也仿版,最重要的是成本很低。
硬體負載均衡是指在多臺伺服器間安裝相應的負載均衡裝置,也就是負載均衡器(如F5)來完成均衡負載技術,與軟體負載均衡技術相比,能達到更好的負載均衡效果。由於硬體負載均衡技術需要額外的增加負載均衡器,成本比較高,所以適用於流量高的大型網站系統。
這裡主要討論的是如何有效的對RabbitMQ叢集使用軟體負載均衡技術,目前主流的方式有在客戶端內部實現負載均衡,或者使用HAProxy、LVS等負載均衡軟體來實現。
客戶端內部實現負載均衡
對於RabbitMQ而言可以在客戶端連線時簡單的使用負載均衡演算法來實現負載均衡。負載均衡演算法有很多種,主流的有:
輪詢法
將請求按順序輪流地分配到後端伺服器上,它均衡地對待後端的每一臺伺服器,而不關係伺服器實際的連線數和當前的系統負載。
示例如程式碼清單所示,如果多個客戶端需要連線到這個有3個節點的RabbitMQ叢集,可以呼叫RoundRobin.getConnectionAddress()來獲取相應的連線地址。
public class RoundRobin {
private static List<String> list = new ArrayList<String>(){{
add("192.168.0.2");
add("192.168.0.3");
add("192.168.0.4");
}};
private static int pos = 0;
private static final Object lock = new Object();
public static String getConnectionAddress(){
String ip = null;
synchronized (lock) {
ip = list.get(pos);
if (++pos >= list.size()) {
pos = 0;
}
}
return ip;
}
}
隨機法
通過隨機演算法,根據後端伺服器的列表大小值來隨機選取其中的一臺伺服器進行訪問。由概率統計理論可以得知,隨著客戶端呼叫服務端的次數增多,其實際效果越來越接近於平均分配呼叫量到後端的每一臺伺服器,也就是輪詢的結果。對應的示例程式碼如下:
public class RandomAccess {
private static List<String> list = new ArrayList<String>(){{
add("192.168.0.2");
add("192.168.0.3");
add("192.168.0.4");
}};
public static String getConnectionAddress(){
Random random = new Random();
int pos = random.nextInt(list.size());
return list.get(pos);
}
}
源地址雜湊法
源地址雜湊的思想是根據獲取的客戶端IP地址,通過雜湊函式計算得到的一個數值,用該數值對伺服器列表的大小進行取模運算,得到的結果便是客戶端要訪問伺服器的序號。採用源地址雜湊法進行負載均衡,同一IP地址的客戶端,當後端伺服器列表不變時,它每次都會對映到同一臺後端伺服器進行訪問。
public class IpHash {
private static List<String> list = new ArrayList<String>(){{
add("192.168.0.2"); add("192.168.0.3"); add("192.168.0.4");
}};
public static String getConnectionAddress() throws UnknownHostException {
int ipHashCode = InetAddress.getLocalHost().getHostAddress().hashCode();
int pos = ipHashCode % list.size();
return list.get(pos);
}
}
加權輪詢法
不同的後端伺服器可能機器的配置和當前系統的負載並不相同,因此它們的抗壓能力也不相同。給配置高、負載低的機器配置更高的權重,讓其處理更多的請求;而配置低、負載高的叢集,給其分配較低的權重,降低其系統負載,加權輪詢能很好地處理這一問題,並將請求順序且按照權重分配到後端。
加權隨機法
與加權輪詢法一樣,加權隨機法也根據後端機器的配置、系統的負載分配不同權重。不同的是,它是按照權重隨機請求後端伺服器,而非順序。
最小連線數法
最小連線數演算法比較靈活和智慧,由於後端伺服器的配置不盡相同,對於請求的處理有塊有慢,它是根據後端伺服器當前的連線情況,動態地選取其中當前積壓連線數最少的一臺伺服器來處理當前的請求,儘可能地提高後端服務的利用效率,將負載合理地分流到每一臺伺服器。
有關於加權輪詢法、加權隨機法和最小連線數法的實現也比較簡單,這裡就留給讀者自己動手實踐一下。
歡迎支援《RabbitMQ實戰指南》以及關注微信公眾號:朱小廝的部落格。