Ribbon核心組件IRule
IRule:根據特定算法中從服務列表中選取一個要訪問的服務
IRule中的均衡算法:
RoundRobinRule 輪詢
RandomRule 隨機
AvailabilityFilteringRule 會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,
還有並發的連接數量超過閾值的服務,然后對剩余的服務列表按照輪詢策略進行訪問
WeightedResponseTimeRule 根據平均響應時間計算所有服務的權重,響應時間越快服務權重越大被選中的概率越高。
剛啟動時如果統計信息不足,則使用RoundRobinRule策略,等統計信息足夠,
會切換到WeightedResponseTimeRule
RetryRule 先按照RoundRobinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重 試,獲取可用的服務
BestAvailableRule 會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然后選擇一個並發量最小的 服務
ZoneAvoidanceRule 默認規則,復合判斷server所在區域的性能和server的可用性選擇服務器
IRule中負載均衡的使用規則是:如果沒有在配置類顯示聲明,就默認使用 RoundRobinRule 輪詢負載均衡算法
如何顯示聲明算法:
在configBean 中 做如下配置:
@Bean
public IRule myRule() {
return new RetryRule();//用我們重新選擇的隨機算法替代默認的輪詢。
}
自定義配置:
在啟動該微服務的時候就能去加載我們的自定義Ribbon配置類,從而使配置生效,形如:
@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
在啟動類之上新建一個包myrule ,然后新建一個MySelfRule類
package cn.blogsx.myrule;
/**
* @author Alex
* @create 2020-02-23 15:53
**/
public class MySelfRule {
@Bean
public IRule myRule() {
return new RandomRule();
}
}
此時仍然為 系統已有隨機算法,不過已經可以在此基礎上修改了。
在MySelfRule類同一包下,新建一個CustomRandomRule 自定義隨機規則類,並實現想要的算法:
依舊輪詢策略,但是加上新需求,每個服務器要求被調用5次。也即
以前是每台機器一次,現在是每台機器5次
package cn.blogsx.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author Alex
* @create 2020-02-23 19:37
**/
@Configuration
public class CustomRandomRule extends AbstractLoadBalancerRule {
private int total = 0; //總共被調用的次數,目前要求每台被調用5次
private int currentIndex = 0; //當前提供服務的機器號
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers();
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
if (total < 5) {
server = upList.get(currentIndex);
total++;
} else {
total = 0;
currentIndex++;
if (currentIndex >= upList.size()) {
currentIndex = 0;
}
}
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;
}
if (server.isAlive()) {
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
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) {
}
}
如此進行測試即可看到每台實例被連續訪問5次,且5次后自動輪詢修改服務實例