Eureka源碼分析 封裝源碼api boolean 值 isReplication作用 二次Replication 等記錄

一.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.需要研究二次註冊問題的,可以繼續深挖,看看最後還有什麼是本人沒有發現的,期待有大神解決了艾特一下我!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章