Eureka中的同步

源码不能添注释,搬运一下。

public int syncUp() {
		//获取到的注册节点数量
        int count = 0;
		//如果count==0,默认重试五次(serverConfig.getRegistrySyncRetryWaitMs()默认为5)
        for(int i = 0; i < this.serverConfig.getRegistrySyncRetries() && count == 0; ++i) {
            if (i > 0) {
                try {
                	//从第二次开始,每次默认沉睡30秒
                    Thread.sleep(this.serverConfig.getRegistrySyncRetryWaitMs());
                } catch (InterruptedException var10) {
                    logger.warn("Interrupted during registry transfer..");
                    break;
                }
            }
			//从本地内存里获取注册实例信息
            Applications apps = this.eurekaClient.getApplications();
            //获取迭代器
            Iterator var4 = apps.getRegisteredApplications().iterator();
			
            while(var4.hasNext()) {
                Application app = (Application)var4.next();
                Iterator var6 = app.getInstances().iterator();

                while(var6.hasNext()) {
                    InstanceInfo instance = (InstanceInfo)var6.next();

                    try {
                    	//判断当前节点是否可以注册
                        if (this.isRegisterable(instance)) {
                        	//注册到当前Eureka Server里
                            this.register(instance, instance.getLeaseInfo().getDurationInSecs(), true);
                            ++count;
                        }
                    } catch (Throwable var9) {
                        logger.error("During DS init copy", var9);
                    }
                }
            }
        }

        return count;
    }
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);
        //注册完成后,发起同步,这里同步类型为Register
        this.replicateToPeers(PeerAwareInstanceRegistryImpl.Action.Register, 
        info.getAppName(), info.getId(), info, (InstanceStatus)null, isReplication);
    }
private void replicateToPeers(PeerAwareInstanceRegistryImpl.Action action, 
String appName, String id, InstanceInfo info, InstanceStatus newStatus, boolean isReplication) {
        Stopwatch tracer = action.getTimer().start();
		
        try {
            //判断是否集群同步请求,如果是,记录最后一分钟的同步次数
            if (isReplication) {
                this.numberOfReplicationsLastMin.increment();
            }
			//如果集群节点非空,并且不是集群同步请求
            if (this.peerEurekaNodes != Collections.EMPTY_LIST && !isReplication) {
                Iterator var8 = this.peerEurekaNodes.getPeerEurekaNodes().iterator();
				//遍历相邻的Eureka Server请求,分别发起请求同步
                while(var8.hasNext()) {
                    PeerEurekaNode node = (PeerEurekaNode)var8.next();
                    //判断是否是自身的url,过滤掉
                    if (!this.peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
                    	//发起同步请求
                        this.replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
                    }
                }

                return;
            }
        } finally {
            tracer.stop();
        }
    }
private void replicateInstanceActionsToPeers(PeerAwareInstanceRegistryImpl.Action action, 
String appName, String id, InstanceInfo info, InstanceStatus newStatus, PeerEurekaNode node) {
        try {
            InstanceInfo infoFromRegistry = null;
            CurrentRequestVersion.set(Version.V2);
            switch(action) {
            case Cancel: //下线
                node.cancel(appName, id);
                break;
            case Heartbeat: //心跳
                InstanceStatus overriddenStatus = (InstanceStatus)this.overriddenInstanceStatusMap.get(id);
                //获取本地最新的实例信息
                infoFromRegistry = this.getInstanceByAppAndId(appName, id, false);
                node.heartbeat(appName, id, infoFromRegistry, overriddenStatus, false);
                break;
            case Register: //注册
                node.register(info);
                break;
            case StatusUpdate: //设置覆盖状态
                infoFromRegistry = this.getInstanceByAppAndId(appName, id, false);
                node.statusUpdate(appName, id, newStatus, infoFromRegistry);
                break;
            case DeleteStatusOverride: //删除覆盖状态
                infoFromRegistry = this.getInstanceByAppAndId(appName, id, false);
                node.deleteStatusOverride(appName, id, infoFromRegistry);
            }
        } catch (Throwable var9) {
            logger.error("Cannot replicate information to {} for action {}", new Object[]{node.getServiceUrl(), action.name(), var9});
        }
    }
public void register(final InstanceInfo info) throws Exception {
        long expiryTime = System.currentTimeMillis() + (long)getLeaseRenewalOf(info);
        //批处理
        this.batchingDispatcher.process(taskId("register", info), 
        new InstanceReplicationTask(this.targetHost, Action.Register, info,
         (InstanceStatus)null, true) {
            public EurekaHttpResponse<Void> execute() {
                return PeerEurekaNode.this.replicationClient.register(info);
            }
        }, expiryTime);
    }

默认采用的是批量任务处理器,就是将task放入任务队列中,然后通过线程获取任务队列里面的任务,模仿ThreadExecutorPool的方式,生成线程,
从队列里面抓取任务处理,统一批量执行,Eureka Server 那边也是统一接收,这样提高了同步效率。

批量处理的任务执行器是com.netflix.eureka.cluster.ReplicationTaskProcessor。

@Path("batch")
@POST
public Response batchReplication(ReplicationList replicationList) {
    try {
        ReplicationListResponse batchResponse = new ReplicationListResponse();
        Iterator var3 = replicationList.getReplicationList().iterator();
		//循环请求的任务
        while(var3.hasNext()) {
            ReplicationInstance instanceInfo = (ReplicationInstance)var3.next();
            try {
                //分发任务,同时将处理结果收集起来,等会统一返回
                batchResponse.addResponse(this.dispatch(instanceInfo));
            } catch (Exception var6) {
                batchResponse.addResponse(new ReplicationInstanceResponse
                (Status.INTERNAL_SERVER_ERROR.getStatusCode(), (InstanceInfo)null));
                logger.error("{} request processing failed for batch item {}/{}", 
                new Object[]{instanceInfo.getAction(), instanceInfo.getAppName(), 
                instanceInfo.getId(), var6});
            }
        }
        return Response.ok(batchResponse).build();
    } catch (Throwable var7) {
        logger.error("Cannot execute batch Request", var7);
        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
    }
}

private ReplicationInstanceResponse dispatch(ReplicationInstance instanceInfo) {
    ApplicationResource applicationResource = 
    this.createApplicationResource(instanceInfo);
    InstanceResource resource = 
    this.createInstanceResource(instanceInfo, applicationResource);
    //获取客户端instance的最后的时间戳
    String lastDirtyTimestamp = toString(instanceInfo.getLastDirtyTimestamp());
    //获取覆盖状态
    String overriddenStatus = toString(instanceInfo.getOverriddenStatus());
    //获取instance状态
    String instanceStatus = toString(instanceInfo.getStatus());
    Builder singleResponseBuilder = new Builder();
    switch(instanceInfo.getAction()) {
    	case Register: //注册
        	singleResponseBuilder = handleRegister(instanceInfo, applicationResource);
        	break;
    	case Heartbeat: //心跳
        	singleResponseBuilder = handleHeartbeat(this.serverConfig, resource, 
        	lastDirtyTimestamp, overriddenStatus, instanceStatus);
        	break;
    	case Cancel: //下线
        	singleResponseBuilder = handleCancel(resource);
        	break;
    	case StatusUpdate: //修改覆盖状态
        	singleResponseBuilder = handleStatusUpdate(instanceInfo, resource);
        	break;
	    case DeleteStatusOverride: //删除覆盖状态
	        singleResponseBuilder = handleDeleteStatusOverride(instanceInfo, resource);
    	}
    return singleResponseBuilder.build();
}    
private static Builder handleRegister(ReplicationInstance instanceInfo, 
ApplicationResource applicationResource) {
	// 调用Application控制层的接口,添加实例
    applicationResource.addInstance(instanceInfo.getInstanceInfo(), "true");
    return (new Builder()).setStatusCode(Status.OK.getStatusCode());
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Zookeeper与Eureka都是用于实现分布式系统的服务注册与发现的工具。 Zookeeper是一个开源的分布式协调服务,主要用于解决分布式应用的一致性问题。它提供了一个分布式的、高可用的、有序的节点存储服务,可以被广泛应用于分布式数据、分布式协调、分布式锁等场景。Zookeeper的核心概念是Znode,可以通过创建、删除、更新、监控Znode来实现分布式系统的数据管理与同步。在服务注册与发现场景,Zookeeper可以作为一个注册心,每个服务实例将自己注册到Zookeeper上,其他服务通过监听Zookeeper上的节点变化来实现服务的发现。 Eureka是Netflix开源的一个服务注册与发现框架,主要用于构建具有弹性的、可水平扩展的微服务体系。Eureka采用了一种去心化的架构,通过将服务注册信息存储在各个节点上来实现高可用性与水平扩展。Eureka具有自我保护机制,能够在网络不稳定或者部分节点宕机的情况下保证服务的正常运行。在Eureka,每个服务实例称为一个应用,通过心跳机制注册自己的信息到Eureka Server上。其他服务可以通过查询Eureka Server来获取可用服务实例的信息,实现服务的发现与负载均衡。 总的来说,Zookeeper与Eureka都是用于实现服务注册与发现的工具,但在实现方式、架构以及功能上存在一些区别。Zookeeper更强调数据一致性与分布式协调,而Eureka则更注重可扩展性与弹性。选择使用哪个工具取决于具体的需求与场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值