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.需要研究二次注册问题的,可以继续深挖,看看最后还有什么是本人没有发现的,期待有大神解决了艾特一下我!

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