一.Eureka源碼分析-Eureka的核心類:
1.InstanceInfo.java(主要的記錄實例的基礎信息com.netflix.appinfo.InstanceInfo.java)
2.LeaseInfo.java(記錄服務實例的租約信息com.netflix.appinfo.LeaseInfo.java)
3.LeaseManager.java(定義服務中心的一般操作接口com.netflix.eureka.lease.LeaseManager.java)
public interface LeaseManager<T> {
//註冊方法
void register(T var1, int var2, boolean var3);
//刪除服務方法
boolean cancel(String var1, String var2, boolean var3);
//服務發送心跳
boolean renew(String var1, String var2, boolean var3);
//剔除租約到期的方法(委託一個定時器時間定時在執行)
void evict();
}
LeaseManager主要的實現類是:PeerAwareInstanceRegistryImpl.java
4.LookupService.java(定義client從服務端獲取信息的接口方法 com.netflix.discovery.shared.LookupService.java)
public interface LookupService<T> {
//通過實例的appName去獲取服務實例 Application.java中含有InstanceInfo的信息
Application getApplication(String var1);
////通過所有的註冊服務實例
Applications getApplications();
//通過appName(有些稱爲appId)去獲取一個服務實例
List<InstanceInfo> getInstancesById(String var1);
//var1 傳入的是virtuaHostname去獲取下一個服務實例
InstanceInfo getNextServerFromEureka(String var1, boolean var2);
}
LookupService的實現類主要是:DiscoveryClient.java
比較重要的方法如下看名稱就知道是幹什麼的啦,就不一一標註了:
二.封裝源碼api
方式一:自己寫接口,通過restTemplate client 去掉用Eureka提供的官方api(自行百度),需要返回json請在請求頭中加上Accept 字段.
方式二:因爲源碼中有部分的方法是受保護或私有的,根據需求對源碼進行注入或者覆寫部分代碼,封裝自己需要的返回字段就行!
三.源碼中的Replication(是否同步複製信息)
如果集羣中有 1, 2 ,3三個實例,1配2, 2配3, 3配1, 形成鏈式集羣,那麼當向1註冊一個新服務時,只有1, 2兩個Eureka實例會有新服務的註冊信息,3是沒有的。這一點在官方wiki上並沒有明確說明。
一般情況下,直接去源碼的core包中翻看,不出所料,找到一個ApplicationsResource.java 其中有個getApplicationResource()方法
下一步發現ApplicationsResource委託給了ApplicationResource.java
可以發現,默認的服務註冊isReplication 是從header中的"x-netflix-discovery-replication"是不是爲"true"來決定的,同步請求會在header中加上自定義的x-netflix-discovery-replication頭:
public static final String HEADER_REPLICATION = "x-netflix-discovery-replication";
假如現在傳入的isReplication=ture我們繼續往下走來到它的實現類 PeerAwareInstanceRegistryImpl.java :275行
public void register(InstanceInfo info, boolean isReplication) {
int leaseDuration = 90;
if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
leaseDuration = info.getLeaseInfo().getDurationInSecs();
}
//調用父類的註冊方法
super.register(info, leaseDuration, isReplication);
//然後調用同步方法(本類415行)假如此時isReplication爲true
this.replicateToPeers(PeerAwareInstanceRegistryImpl.Action.Register, info.getAppName(), info.getId(), info, (InstanceStatus)null, isReplication);
}
PeerAwareInstanceRegistryImpl.java :415行
private void replicateToPeers(PeerAwareInstanceRegistryImpl.Action action, String appName, String id, InstanceInfo info, InstanceStatus newStatus, boolean isReplication) {
//時間日誌工具先不管
Stopwatch tracer = action.getTimer().start();
try {
if (isReplication) {
//最小重複次數自增1L
this.numberOfReplicationsLastMin.increment();
}
// 看條件如果peerEurekaNodes 不爲空(同步不一般都不爲空)
//但是假設isReplication 爲true, 是個同步註冊信息的請求
//!isReplication這裏就直接返回false了
if (this.peerEurekaNodes != Collections.EMPTY_LIST && !isReplication) {
Iterator var8 = this.peerEurekaNodes.getPeerEurekaNodes().iterator();
// 向自己的peer節點同步註冊信息
while(var8.hasNext()) {
PeerEurekaNode node = (PeerEurekaNode)var8.next();
if (!this.peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
this.replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
}
}
return;
}
} finally {
tracer.stop();
}
}
假設isReplication 爲true, 是個同步註冊信息的請求(!isReplication)這裏就直接返回false了 目前源碼版本爲:1.9.13
還有個不知名的版本源碼是這樣的:
private void replicateToPeers(Action action, String appName, String id,
InstanceInfo info /* optional */,
InstanceStatus newStatus /* optional */, boolean isReplication) {
Stopwatch tracer = action.getTimer().start();
try {
// ... ...
// isReplication=ture這裏就直接返回了
if (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {
return;
}
for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {
if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
continue;
}
replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
}
} finally {
tracer.stop();
}
}
嘗試看看最新版本中是不是有所變化,於是引入最新maven試試:
很遺憾的是,目前最新版本1.9.22中和1.9.13的源碼是一樣的,所以關於二次註冊同步的問題.是作者有意而爲之,並不是bug.
空了,再找其他的資料看看吧!
四.總結
1.需要封裝自己的eureka服務的可以參看本次記錄,甚至可以集成部分CRUD頁面,做一個服務的維護增強,因爲我就是這樣做的,哈哈哈哈!
2.需要研究二次註冊問題的,可以繼續深挖,看看最後還有什麼是本人沒有發現的,期待有大神解決了艾特一下我!