前言
Dubbo 是一個分佈式服務框架,一個服務可能會部署多個實例,我們應該如何從多個服務提供者組成的集羣挑選一個進行調用呢?這就涉及到一個負載均衡的問題。
四種負載均衡策略
Dubbo 內置了四種負載均衡策略,分別如下:
- RandomLoadBalance:隨機負載均衡
- RoundRobinLoadBalance:輪詢負載均衡
- LeastActiveLoadBalance:最少活躍調用數負載均衡
- ConsistentHashLoadBalance:一致性哈希負載均衡
下面我們對這四種負載均衡策略做一個簡單的介紹。
隨機負載均衡
隨機負載均衡是 Dubbo 默認的負載均衡策略,顧名思義,就是從多個服務提供者中隨機選擇一個。
需要注意的是,Dubbo 的隨機負載均衡並非是完全的隨機,它有一個權重的概念,會按照權重來設置隨機概率,舉個例子,我們現在有兩個服務提供者,一個的權重是100,另一個的權重是300,那麼前者被分配的概率就爲 25%,後者被分配的概率爲 75%。
我們可以對服務提供者設置不同的權重,例如對性能較好的機器設置大權重,對差一點的機器設置小一點的權重。
輪詢負載均衡
輪詢負載均衡,即會輪詢每一個服務提供者,依次對其進行調用。
輪詢負載均衡也有權重的概念,可以嚴格按照我們設置的比例進行分配,這個是該算法的優點,不過,該算法的缺點也很明顯,可能會存在較慢的機器,那麼請求會在這臺機器上進行累積,很容易導致整個系統變慢。
最少活躍調用數負載均衡
最少活躍調用數負載均衡會將請求轉發至活躍調用數最少的機器上,如果有兩臺機器活躍數相同,會採取隨機負載均衡的策略。
什麼是活躍調用數呢?每個服務維護一個活躍數計數器,該計數器存放機器未處理完的請求。當有請求產生時,會選擇活躍數最小的機器去執行。
最少活躍調用數負載均衡可以令慢的機器收到更少的請求。
一致性哈希負載均衡
要了解這種負載均衡策略,我們首先得學習一下一致性哈希算法。不會一致性哈希算法的同學可以看一下我之前寫的這篇博客,質量保證過硬:一致性哈希算法詳解
一致性哈希可以保證相同參數的請求一定會發送到同一臺機器上,即使有機器崩潰,由於一致性哈希算法的特性與虛擬節點的存在,發往該機器的請求會被髮送到其它機器上,並不會引發劇烈變動。
配置
我們可以在多個地方(客戶端,服務端),以多個級別(方法級,接口級,全局配置)配置負載均衡。它們之間的優先關係如下:
- 方法級優先,接口級次之,全局配置再次之
- 如果級別一樣,則消費方優先,提供方次之
實現
我們創建兩個服務提供者,兩個服務提供者的實現分別如下,它們提供的返回值是不同的。
package edu.szu.producer.serviceImpl;
import com.alibaba.dubbo.config.annotation.Service;
import edu.szu.api.service.NameService;
import org.springframework.stereotype.Component;
@Component
@Service
public class NameServiceImpl implements NameService {
@Override
public String updateName(String name) {
return "舊機器:" + name;
}
}
package edu.szu.producer_new.serviceImpl;
import com.alibaba.dubbo.config.annotation.Service;
import edu.szu.api.service.NameService;
import org.springframework.stereotype.Component;
@Component
@Service
public class NameServiceImpl implements NameService {
@Override
public String updateName(String name) {
return "新機器:" + name;
}
}
我們發起十次遠程調用,其返回值分別如下:
舊機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
新機器:HelloDubbo
新機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
新機器:HelloDubbo
我們可以發現,在默認情況下,其採取的是隨機的負載均衡策略。如果我們想要換一種負載均衡策略,例如就換成輪詢負載均衡,應該怎麼實現呢?
我們修改一下服務消費者的代碼,在 @Reference 註解中添加一個 loadbalance 屬性來指定負載均衡策略。
package edu.szu.consumer.serviceImpl;
import com.alibaba.dubbo.config.annotation.Reference;
import edu.szu.api.service.NameService;
import edu.szu.consumer.service.ChangeService;
import org.springframework.stereotype.Component;
@Component
public class ChangeServiceImpl implements ChangeService {
@Reference(loadbalance = "roundrobin")
NameService nameService;
@Override
public String change(String name) {
return nameService.updateName(name);
}
}
然後我們再發起十次遠程調用,其返回值分別如下:
舊機器:HelloDubbo
新機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
舊機器:HelloDubbo
新機器:HelloDubbo
可見其完全遵循了輪詢的規則,也證明了我們的負載均衡策略設置成功。
參考:Dubbo的負載均衡