github 解析源碼:https://github.com/Netflix/ribbon/blob/master/ribbonloadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java
1.Ribbon 負載均衡算法架構圖
總結:可以看出Ribbon架構采用的都是基于一個接口提供規範,抽象類實作基礎功能,子類繼承抽象類 實作自己特有的算法。而常見的java 中間件常用架構都是采用類似的思想進行架構的設計。
2.随機算法代碼解析
package com.hblg.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author i
* @create 2020/2/19 17:46
* @Description RandomRule Ribbon随機通路算法
*/
//繼承第二階梯的抽象類
public class RandomRule extends AbstractLoadBalancerRule {
/**
* Randomly choose from all living servers
*/
public Server choose(ILoadBalancer lb, Object key) {
//先判斷負載均衡是否為空 為空直接傳回
if (lb == null) {
return null;
}
Server server = null;
//使用while 而不是用if 為的是在server==null 在進行依次判斷 避免因多線程操作server資料的線程安全問題
while (server == null) {
//如果目前線程是中斷狀态 直接傳回
if (Thread.interrupted()) {
return null;
}
//擷取到線上微服務清單
List<Server> upList = lb.getReachableServers();
//擷取到所有包含線上和可能因網絡擁堵出現的異常服務清單
List<Server> allList = lb.getAllServers();
//擷取到所有的服務的數量
int serverCount = allList.size();
//如果數量為0 直接傳回null
if (serverCount == 0) {
/*
* No servers. End regardless of pass, because subsequent passes
* only get more restrictive.
*/
return null;
}
//根據目前服務清單數量 随機生成一個生産者節點下标
int index = chooseRandomInt(serverCount);
server = upList.get(index);
//如果目前server節點為null 目前線程讓步 繼續下一次
if (server == null) {
/*
* The only time this should happen is if the server list were
* somehow trimmed. This is a transient condition. Retry after
* yielding.
*/
Thread.yield();
continue;
}
//如果目前Server節點 是活躍狀态直接傳回 使用
if (server.isAlive()) {
return (server);
}
//為了避免其他情況的出現 設定目前Server節點為null 線程讓步
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
/***
* ThreadLocalRandom用内部生成的種子進行初始化,可能不會被修改。
* 适用時,在并發程式中使用ThreadLocalRandom而不是共享的Random對象通常會遇到更少的開銷和争用。
* 當多個任務(例如,每個ForkJoinTask )線上程池中并行使用随機數時,使用ThreadLocalRandom是特别合适的。
* @param serverCount
* @return
*/
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}