簡單看看其他的一些ribbon支持的負載均衡算法的IRule的源碼
(1)RoundRobinRule:系統內置的默認負載均衡規範,直接round robin輪詢,從一堆server list中,不斷的輪詢選擇出來一個server,每個server平攤到的這個請求,基本上是平均的
這個算法,說白了是輪詢,就是一臺接着一臺去請求,是按照順序來的
但是我debug源碼時,發現ribbon在做輪詢負載均衡時使用的不是RoundRobinRule裏邊的輪詢算法,而是通過 nextIndex.getAndIncrement() % eligible.size() 來取模實現輪詢負載。不知道是不是和我的ribbon源碼版本有關係,我的版本爲ribbon-2.2.2,如果有人知道,還請留言告知!感謝!
public class RoundRobinRule extends AbstractLoadBalancerRule {
//輪詢算法
private int incrementAndGetModulo(int modulo) {
for (;;) {
//下一個服務器循環計數器nextServerCyclicCounter默認爲0
int current = nextServerCyclicCounter.get();
//modulo爲serverCount,即服務列表size,服務總數量
int next = (current + 1) % modulo;
if (nextServerCyclicCounter.compareAndSet(current, next))
return next;
}
}
}
(2)AvailabilityFilteringRule:這個rule就是會考察服務器的可用性
如果3次連接失敗,就會等待30秒後再次訪問;如果不斷失敗,那麼等待時間會不斷邊長
如果某個服務器的併發請求太高了,那麼會繞過去,不再訪問
先用round robin算法,輪詢依次選擇一臺server,如果判斷這個server是存活的可用的,如果這臺server是不可以訪問的,那麼就用round robin算法再次選擇下一臺server,依次循環往復,10次。
public class AvailabilityFilteringRule extends PredicateBasedRule {
@Override
public Server choose(Object key) {
int count = 0;
Server server = roundRobinRule.choose(key);
while (count++ <= 10) {
if (predicate.apply(new PredicateKey(server))) {
return server;
}
server = roundRobinRule.choose(key);
}
return super.choose(key);
}
}
(3)WeightedResponseTimeRule:帶着權重的,每個服務器可以有權重,權重越高優先訪問,如果某個服務器響應時間比較長,那麼權重就會降低,減少訪問
public class WeightedResponseTimeRule extends RoundRobinRule {
@Override
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
// get hold of the current reference in case it is changed from the other thread
List<Double> currentWeights = accumulatedWeights;
if (Thread.interrupted()) {
return null;
}
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
int serverIndex = 0;
// last one in the list is the sum of all weights
double maxTotalWeight = currentWeights.size() == 0 ? 0 : currentWeights.get(currentWeights.size() - 1);
// No server has been hit yet and total weight is not initialized
// fallback to use round robin
if (maxTotalWeight < 0.001d) {
server = super.choose(getLoadBalancer(), key);
if(server == null) {
return server;
}
} else {
// generate a random weight between 0 (inclusive) to maxTotalWeight (exclusive)
double randomWeight = random.nextDouble() * maxTotalWeight;
// pick the server index based on the randomIndex
int n = 0;
for (Double d : currentWeights) {
if (d >= randomWeight) {
serverIndex = n;
break;
} else {
n++;
}
}
server = allList.get(serverIndex);
}
if (server == null) {
/* Transient. */
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Next.
server = null;
}
return server;
}
}
(4)ZoneAvoidanceRule:根據機房和服務器來進行負載均衡,說白了,就是機房的意思,看了源碼就是知道了,這個就是所謂的spring cloud ribbon環境中的默認的Rule
public class ZoneAvoidanceRule extends PredicateBasedRule {
static String randomChooseZone(Map<String, ZoneSnapshot> snapshot,
Set<String> chooseFrom) {
if (chooseFrom == null || chooseFrom.size() == 0) {
return null;
}
String selectedZone = chooseFrom.iterator().next();
if (chooseFrom.size() == 1) {
return selectedZone;
}
int totalServerCount = 0;
for (String zone : chooseFrom) {
totalServerCount += snapshot.get(zone).getInstanceCount();
}
int index = random.nextInt(totalServerCount) + 1;
int sum = 0;
for (String zone : chooseFrom) {
sum += snapshot.get(zone).getInstanceCount();
if (index <= sum) {
selectedZone = zone;
break;
}
}
return selectedZone;
}
}
下邊幾種不常用的IRule就不貼源碼了。。。
(5)BestAvailableRule:忽略那些請求失敗的服務器,然後儘量找併發比較低的服務器來請求
(6)RandomRule:隨機找一個服務器,儘量將流量分散在各個服務器上
(7)RetryRule:可以重試,就是通過round robin找到的服務器請求失敗,可以重新找一個服務器