🍊 Java學(xué)習(xí):社區(qū)快速通道
🍊 深入淺出RocketMQ設(shè)計思想:深入淺出RocketMQ設(shè)計思想
🍊 絕對不一樣的職場干貨:大廠最佳實踐經(jīng)驗指南
📆 最近更新:2023年7月2日
🍊 點贊 👍 收藏 ?留言 📝 都是我最大的動力!
IPing機制
Ribbon
會主動判斷服務(wù)節(jié)點的當(dāng)前狀態(tài),決定是否可作為目標(biāo)節(jié)點,只有當(dāng)前可用的節(jié)點才會作為負載均衡器的目標(biāo)節(jié)點,。IPing有以下幾個手段:
DummyPing
:默認返回true,即認為所有節(jié)點都可用,這也是單獨使用Ribbon時的默認模式NIWSDiscoveryPing
:借助Eureka服務(wù)發(fā)現(xiàn)機制獲取節(jié)點狀態(tài),假如節(jié)點狀態(tài)是UP則認為是可用狀態(tài)PingUrl
:主動向服務(wù)節(jié)點發(fā)起一次http調(diào)用,如果對方有響應(yīng)則認為節(jié)點可用PingConstant
:返回設(shè)置的常量值NoOpPing
:返回true
假如服務(wù)節(jié)點搭載的服務(wù)本身就承載超高并發(fā)的情況下,那這種主動出擊的IPing
策略必然會大大增加服務(wù)節(jié)點的訪問壓力,。
Ribbon IPing是一個接口,可以通過實現(xiàn)該接口來自定義Ping機制,。Ribbon IPing的實現(xiàn)類需要在配置文件或者代碼中指定,例如:
#單個服務(wù)設(shè)置
[service-name]:
ribbon:
NFLoadBalancerPingClassName: com.netflix.loadbalancer.DummyPing
public class MicroRibbonConfig {
@Bean
public IPing microIPing() {
return new DummyPing();
}
}
@RibbonClient(name = "micro-service", configuration = MicroRibbonConfig.class)
public class RibbonClientConfig {
}
Ribbon IPing的作用是保證負載均衡器只選擇可用的服務(wù)節(jié)點,提高系統(tǒng)的可靠性和性能,。Ribbon IPing與Eureka結(jié)合使用時,可以實現(xiàn)自動化的服務(wù)發(fā)現(xiàn)和健康檢查,。
用時間換空間
在Ribbon這里,時間和空間經(jīng)常要被換來換去,時間代表著接口響應(yīng)時間(RT,Response Time),空間表示服務(wù)器的可用連接數(shù),。
在Ribbon里有兩個和時間與空間密切相關(guān)的負載均衡策略,BestAvailableRule
(簡稱BA)和WeightedResponseTimeRule
。他們都會選擇壓力較小的服務(wù)節(jié)點,但這兩個策略的方向不同,。BA會根據(jù)服務(wù)節(jié)點過去一段時間的請求數(shù),選擇并發(fā)量最小的機器(選擇空間);WRT則是根據(jù)響應(yīng)時間的統(tǒng)計結(jié)果,選擇響應(yīng)時間最快的服務(wù)(選擇時間),。
- 連接數(shù)敏感模型: 對響應(yīng)時間較短,或RT和業(yè)務(wù)復(fù)雜度是非線性相關(guān)關(guān)系的接口,采用基于可用連接數(shù)的負載均衡策略更加合適。
- RT敏感模型: 對重量級接口,尤其是根據(jù)參數(shù)不同會導(dǎo)致系統(tǒng)資源使用率浮動較大的接口(RT與業(yè)務(wù)復(fù)雜度線性相關(guān)),建議采用基于響應(yīng)時間的負載均衡策略,。
總結(jié)一下就是輕量級接口選空間(BestAvailableRule
),、重量級接口選時間(WeightedResponseTimeRule
)
Ribbon IPing機制源碼探秘
IPing接口的定義如下:
public interface IPing {
public boolean isAlive(Server server);
}
看一下它的幾個實現(xiàn)類:
public class DummyPing extends AbstractLoadBalancerPing {
public DummyPing() {
}
public boolean isAlive(Server server) {
return true;
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
什么都沒發(fā)生,直接返回true
public class NoOpPing implements IPing {
@Override
public boolean isAlive(Server server) {
return true;
}
}
也是直接返回true
PingUrl
的內(nèi)容比較豐富,關(guān)注一下isAlive
方法:
public boolean isAlive(Server server) {
String urlStr = "";
if (this.isSecure) {
urlStr = "https://";
} else {
urlStr = "http://";
}
urlStr = urlStr + server.getId();
urlStr = urlStr + this.getPingAppendString();
boolean isAlive = false;
HttpClient httpClient = new DefaultHttpClient();
HttpUriRequest getRequest = new HttpGet(urlStr);
String content = null;
try {
HttpResponse response = httpClient.execute(getRequest);
content = EntityUtils.toString(response.getEntity());
isAlive = response.getStatusLine().getStatusCode() == 200;
if (this.getExpectedContent() != null) {
LOGGER.debug("content:" + content);
if (content == null) {
isAlive = false;
} else if (content.equals(this.getExpectedContent())) {
isAlive = true;
} else {
isAlive = false;
}
}
} catch (IOException var11) {
var11.printStackTrace();
} finally {
getRequest.abort();
}
return isAlive;
}
如果是安全協(xié)議則使用https,不是安全的則使用http,拼接的時候先加上一個server.getId()
,再加上一個this.getPingAppendString()
HttpClient httpClient = new DefaultHttpClient();
HttpUriRequest getRequest = new HttpGet(urlStr);
構(gòu)造一個http請求來判斷是否是up狀態(tài)
if (this.getExpectedContent() != null)
如果有返回的期望值,則需要實際返回的數(shù)據(jù)等于期望值才證明是服務(wù)節(jié)點是up的
NIWSDiscoveryPing
實現(xiàn)類:
public boolean isAlive(Server server) {
boolean isAlive = true;
if (server!=null && server instanceof DiscoveryEnabledServer){
DiscoveryEnabledServer dServer = (DiscoveryEnabledServer)server;
InstanceInfo instanceInfo = dServer.getInstanceInfo();
if (instanceInfo!=null){
InstanceStatus status = instanceInfo.getStatus();
if (status!=null){
isAlive = status.equals(InstanceStatus.UP);
}
}
}
return isAlive;
}
只有server
的類型是DiscoveryEnabledServer
才將其轉(zhuǎn)換成自己需要的類型,然后獲得instanceInfo
。
這里InstanceStatus
是依靠eureka
的服務(wù)發(fā)現(xiàn)從服務(wù)注冊中心拉取到的,服務(wù)發(fā)現(xiàn)并不能即使反映所有服務(wù)器的狀態(tài)變化,因為是客戶端發(fā)起的,所以有延遲,。