在這一章我們要學習ribbon如何做負載均衡,從我上面的服務消費者和服務提供者的案例來看.由於上訴案例中只有一個數據庫,所以我們在模擬負載均衡場景的時候應該要考慮多個數據庫.淺顯的將,就是我們在查詢數據庫服務時,我們希望服務器不會總是從一個數據庫上查詢.而是從不同的數據庫中查詢相同的數據,這樣能減少數據庫的壓力.
首先,我們先多建兩個數據庫,數據庫中的數據都是一樣的.但是爲了看出數據庫的差異,我們需要知道當前的數據是從哪一個數據庫中查詢,所以說我們會在每個數據庫後面的字段加上當前的數據庫名.如下圖:
當然我們也需要多準備兩個服務提供者端口:8002,8003.分別綁定對應的數據庫如下圖:
點擊網址查看eureka7001.com/7001
我們可以發現這裏已經有了三個實例
上訴操作完後,我們在瀏覽器中輸入網址localhost/consumer/dept/list.
就能查看數據庫中的數據.而且每次刷新網頁就能是從不同的數據庫中查詢出來的,
但是刷新幾次後我們會發現,這是一個有規律的查詢方式.
這裏就又要談到一個接口IRule.這個接口裏面有很多寫好的一些負載均衡算法:
當然像我們上面的那種有規律的查詢就是這裏方法中的RoundRobinRule.策稱爲輪詢規則.源碼如下:
其中還有一些常用的比如隨機算法,
還有一種是WeightedResponseTimeRule權重算法,計算加權
RetryRule:重試策略,會先按照輪詢獲取服務,如果服務獲取失敗,則會在指定的時間內進行重試.
AvailabilityFilteringRule:會先過濾掉崩潰的服務,跳閘的服務(訪問故障).對剩下的進行輪詢
這些是源碼中提供給我們的一些策略,當然我們可以自己自定義一些算法.
步驟如下:
我們需要在不同於主啓動類的包下新建一個包比如:
第一步:需要在ConfigBean中註冊我們自定義的策略,然後添加@Bean,交由spring託管.
@Bean
public IRule MyIRule(){
return new MyRule();//默認的是輪詢,現在我們自定義的就是我們自己寫的算法
}
第二步: 在主啓動類中添加註釋@@RibbonClient,在微服務加載的時候就能區域加載我們自定義的Ribbon類
//在微服務加載的時候就能區域加載我們自定義的Ribbon類
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRule.class)
第三步:編寫自定義策略代碼:
package com.qiu.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;
public class MyRule extends AbstractLoadBalancerRule {
//要求就是每個機器訪問5次,然後換下一個服務(3個)
//大於三個就置於0
//total=0.默認的也是0,如果=5我們就指向下一個節點
//index=0,默認0,如果total=5,那麼index+1,如果index=3,那麼就將index置爲0
private int total = 0;//被調用的次數
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) {
/*
* No servers. End regardless of pass, because subsequent passes
* only get more restrictive.
*/
return null;
}
// int index = chooseRandomInt(serverCount);//生成區間隨機數
// server = upList.get(index);//從活着的服務中隨機獲取一個
//==============================================
if(total<5){
server = upList.get(currentIndex);
total++;
}else {
total=0;
currentIndex++;
if (currentIndex>upList.size()){//當前的服務(第幾個)大於最大的,則將服務置爲最開始的那一個
currentIndex=0;
}
server = upList.get(currentIndex);//從活着的服務中獲取指定的服務進行操作
}
//=======================================
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
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 clientConfig) {
// TODO Auto-generated method stub
}
}
這裏的代碼可以借鑑源碼給予我們的再進行修改即可.