Eureka服务端源码分析(二)--- 服务端处理客户端请求

本文详细解析了Eureka服务注册、续约、状态更新和剔除的流程,包括服务实例如何注册、心跳续约、状态变化以及服务剔除,并介绍了如何同步这些操作到其他Eureka节点。同时,展示了在同步失败时的处理策略,如处理404和不同步时间戳的情况。
摘要由CSDN通过智能技术生成

ApplicationResource

	//服务实例注册
	@POST
    @Consumes({"application/json", "application/xml"})
    public Response addInstance(InstanceInfo info,
                                @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
        logger.debug("Registering instance {} (replication={})", info.getId(), isReplication);
       
       	//省略部分代码
		
		//"true".equals(isReplication) , 由其他eureka节点同步过来的则为true
        registry.register(info, "true".equals(isReplication));
        return Response.status(204).build();  // 204 to be backwards compatible
    }

InstanceRegistry

	@Override
	public void register(final InstanceInfo info, final boolean isReplication) {
		handleRegistration(info, resolveInstanceLeaseDuration(info), isReplication);
		super.register(info, isReplication);
	}
	//获取实例过期时间
	private int resolveInstanceLeaseDuration(final InstanceInfo info) {
		//默认90s
		int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
		if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
			//获取客户端传递过来的过期时间
			leaseDuration = info.getLeaseInfo().getDurationInSecs();
		}
		return leaseDuration;
	}
	private void handleRegistration(InstanceInfo info, int leaseDuration,
			boolean isReplication) {
		log("register " + info.getAppName() + ", vip " + info.getVIPAddress()
				+ ", leaseDuration " + leaseDuration + ", isReplication "
				+ isReplication);
		//发布EurekaInstanceRegisteredEvent
		publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration,
				isReplication));
	}
	@Override
	public boolean renew(final String appName, final String serverId,
			boolean isReplication) {
		log("renew " + appName + " serverId " + serverId + ", isReplication {}"
				+ isReplication);
		List<Application> applications = getSortedApplications();
		//循环所有的服务实例,根据serverId找到对应的实例
		for (Application input : applications) {
			if (input.getName().equals(appName)) {
				InstanceInfo instance = null;
				for (InstanceInfo info : input.getInstances()) {
					if (info.getId().equals(serverId)) {
						instance = info;
						break;
					}
				}
				//发布续约事件
				publishEvent(new EurekaInstanceRenewedEvent(this, appName, serverId,
						instance, isReplication));
				break;
			}
		}
		return super.renew(appName, serverId, isReplication);
	}
	@Override
	public boolean cancel(String appName, String serverId, boolean isReplication) {
		//发布服务剔除事件
		handleCancelation(appName, serverId, isReplication);	
		return super.cancel(appName, serverId, isReplication);
	}

PeerAwareInstanceRegistryImpl

	@Override
    public void register(final InstanceInfo info, final boolean isReplication) {
    	//默认90s
        int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
        //过期时间优先使用客户段传递过来的属性值
        if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
            leaseDuration = info.getLeaseInfo().getDurationInSecs();
        }
        super.register(info, leaseDuration, isReplication);
        //同步注册的服务信息给给其他eureka节点,发送请求调用其他eureka节点的addInstance逻辑
        replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
    }
    @Override
    public boolean renew(final String appName, final String id, final boolean isReplication) {
        if (super.renew(appName, id, isReplication)) {
        	//将该实例的心跳续约信息同步给其他eureka节点
            replicateToPeers(Action.Heartbeat, appName, id, null, null, isReplication);
            return true;
        }
        return false;
    }
    @Override
    public boolean statusUpdate(final String appName, final String id,
                                final InstanceStatus newStatus, String lastDirtyTimestamp,
                                final boolean isReplication) {
        if (super.statusUpdate(appName, id, newStatus, lastDirtyTimestamp, isReplication)) {
        	//同步给其他eureka节点
            replicateToPeers(Action.StatusUpdate, appName, id, null, newStatus, isReplication);
            return true;
        }
        return false;
    }
    @Override
    public boolean cancel(final String appName, final String id,
                          final boolean isReplication) {
        if (super.cancel(appName, id, isReplication)) {
        	//同步给其他eureka节点
            replicateToPeers(Action.Cancel, appName, id, null, null, isReplication);

            return true;
        }
        return false;
    }

AbstractInstanceRegistry

	public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
        read.lock();
        try {
        	//使用服务名称获取到gMap (实例id 和 实例)
            Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
            REGISTER.increment(isReplication);
            //gMap为空,说明是该服务第一个实例注册过来
            if (gMap == null) {
            	//实例化一个新map
                final ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = new ConcurrentHashMap<String, Lease<InstanceInfo>>();
                //放入registry中
                gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap);
                if (gMap == null) {
                    gMap = gNewMap;
                }
            }
            //使用实例id获取到实例
            Lease<InstanceInfo> existingLease = gMap.get(registrant.getId());
            // Retain the last dirty timestamp without overwriting it, if there is already a lease
            //实例已经存在
            if (existingLease != null && (existingLease.getHolder() != null)) {
            	//获取存在的实例最后的更新时间
                Long existingLastDirtyTimestamp = existingLease.getHolder().getLastDirtyTimestamp();
                //获取注册过来的实例的最后更新时间
                Long registrationLastDirtyTimestamp = registrant.getLastDirtyTimestamp();
                logger.debug("Existing lease found (existing={}, provided={}", existingLastDirtyTimestamp, registrationLastDirtyTimestamp);

                // this is a > instead of a >= because if the timestamps are equal, we still take the remote transmitted
                // InstanceInfo instead of the server local copy.
                //如果存在的实例更新时间更晚,则将registrant 修改为 存在的
                if (existingLastDirtyTimestamp > registrationLastDirtyTimestamp) {
                    logger.warn("There is an existing lease and the existing lease's dirty timestamp {} is greater" +
                            " than the one that is being registered {}", existingLastDirtyTimestamp, registrationLastDirtyTimestamp);
                    logger.warn("Using the existing instanceInfo instead of the new instanceInfo as the registrant");
                    registrant = existingLease.getHolder();
                }
            } 
            //实例不存在
            else {
                synchronized (lock) {
                    if (this.expectedNumberOfClientsSendingRenews > 0) {
                        //新的实例注册上来,则expectedNumberOfClientsSendingRenews 加一
                        this.expectedNumberOfClientsSendingRenews = this.expectedNumberOfClientsSendingRenews + 1;
                        //重新设置 服务端期望每分钟接受到的心跳续约的次数
                        updateRenewsPerMinThreshold();
                    }
                }
                logger.debug("No previous lease information found; it is new registration");
            }
            //实例化lease
            Lease<InstanceInfo> lease = new Lease<InstanceInfo>(registrant, leaseDuration);
            //如果有存在的实例
            if (existingLease != null) {
            	//服务上线时间 设置为 存在的实例的
                lease.setServiceUpTimestamp(existingLease.getServiceUpTimestamp());
            }
            //向gmap中放入实例id和实例的映射关系
            gMap.put(registrant.getId(), lease);
            recentRegisteredQueue.add(new Pair<Long, String>(
                    System.currentTimeMillis(),
                    registrant.getAppName() + "(" + registrant.getId() + ")"));
            if (!InstanceStatus.UNKNOWN.equals(registrant.getOverriddenStatus())) {
                logger.debug("Found overridden status {} for instance {}. Checking to see if needs to be add to the "
                                + "overrides", registrant.getOverriddenStatus(), registrant.getId());
                if (!overriddenInstanceStatusMap.containsKey(registrant.getId())) {
                    logger.info("Not found overridden id {} and hence adding it", registrant.getId());
                    overriddenInstanceStatusMap.put(registrant.getId(), registrant.getOverriddenStatus());
                }
            }
            //设置overriddenStatus
            InstanceStatus overriddenStatusFromMap = overriddenInstanceStatusMap.get(registrant.getId());
            if (overriddenStatusFromMap != null) {
                logger.info("Storing overridden status {} from map", overriddenStatusFromMap);
                registrant.setOverriddenStatus(overriddenStatusFromMap);
            }
			
            InstanceStatus overriddenInstanceStatus = getOverriddenInstanceStatus(registrant, existingLease, isReplication);
            //设置实例状态
            registrant.setStatusWithoutDirty(overriddenInstanceStatus);
			//实例状态为UP
            if (InstanceStatus.UP.equals(registrant.getStatus())) {
            	//更新实例上线时间
                lease.serviceUp();
            }
            //ActionType设置为ADD
            registrant.setActionType(ActionType.ADDED);
            //加入到recentlyChangedQueue (客户段增量同步服务信息使用)
            recentlyChangedQueue.add(new RecentlyChangedItem(lease));
            registrant.setLastUpdatedTimestamp();
            //清除readWriteCacheMap对应服务的缓存信息
            invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress());
            logger.info("Registered instance {}/{} with status {} (replication={})",
                    registrant.getAppName(), registrant.getId(), registrant.getStatus(), isReplication);
        } finally {
            read.unlock();
        }
    }
    public boolean renew(String appName, String id, boolean isReplication) {
        RENEW.increment(isReplication);
        //根据服务名称获取到服务列表
        Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
        Lease<InstanceInfo> leaseToRenew = null;
        if (gMap != null) {
        	//根据实例id获取到具体实例
            leaseToRenew = gMap.get(id);
        }
        //实例不存在,返回false
        if (leaseToRenew == null) {
            RENEW_NOT_FOUND.increment(isReplication);
            logger.warn("DS: Registry: lease doesn't exist, registering resource: {} - {}", appName, id);
            return false;
        } 
        else {
            InstanceInfo instanceInfo = leaseToRenew.getHolder();
            if (instanceInfo != null) {
            	//获取实例的overriddenInstanceStatus 
                InstanceStatus overriddenInstanceStatus = this.getOverriddenInstanceStatus(
                        instanceInfo, leaseToRenew, isReplication);
                if (overriddenInstanceStatus == InstanceStatus.UNKNOWN) {
                    logger.info("Instance status UNKNOWN possibly due to deleted override for instance {}"
                            + "; re-register required", instanceInfo.getId());
                    RENEW_NOT_FOUND.increment(isReplication);
                    return false;
                }
                //判断实例的status 和 overriddenInstanceStatus是否一致
                if (!instanceInfo.getStatus().equals(overriddenInstanceStatus)) {
                    logger.info(
                            "The instance status {} is different from overridden instance status {} for instance {}. "
                                    + "Hence setting the status to overridden status", instanceInfo.getStatus().name(),
                                    overriddenInstanceStatus.name(),
                                    instanceInfo.getId());
                    //不一致,将status 修改为 overriddenInstanceStatus
                    instanceInfo.setStatusWithoutDirty(overriddenInstanceStatus);

                }
            }
            renewsLastMin.increment();
            //更新实例的lastUpdateTimestamp完成续约
            leaseToRenew.renew();
            return true;
        }
    }
    @Override
    public boolean statusUpdate(String appName, String id,
                                InstanceStatus newStatus, String lastDirtyTimestamp,
                                boolean isReplication) {
        read.lock();
        try {
            STATUS_UPDATE.increment(isReplication);
            //服务名称获取到服务实例列表
            Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
            Lease<InstanceInfo> lease = null;
            if (gMap != null) {
            	//服务实例id获取到服务实例
                lease = gMap.get(id);
            }
            //服务实例为空,直接返回false
            if (lease == null) {
                return false;
            } 
            else {
            	//更新lease的lastUpdateTimestamp
                lease.renew();
                InstanceInfo info = lease.getHolder();
                // Lease is always created with its instance info object.
                // This log statement is provided as a safeguard, in case this invariant is violated.
                if (info == null) {
                    logger.error("Found Lease without a holder for instance id {}", id);
                }
                //如果更新的状态 和 原本实例的状态不相等
                if ((info != null) && !(info.getStatus().equals(newStatus))) {
                    //如果将实例状态更新为 UP 
                    if (InstanceStatus.UP.equals(newStatus)) {
                    	//如果serviceUpTimestamp为0 ,则更新lease的serviceUpTimestamp为当前时间
                        lease.serviceUp();
                    }
                    //记录实例的重写的状态
                    overriddenInstanceStatusMap.put(id, newStatus);
					//更新overriddenStatus
                    info.setOverriddenStatus(newStatus);
                    long replicaDirtyTimestamp = 0;
                    //更新status
                    info.setStatusWithoutDirty(newStatus);
                    if (lastDirtyTimestamp != null) {
                        replicaDirtyTimestamp = Long.parseLong(lastDirtyTimestamp);
                    }
                    //如果请求携带的lastDirtyTimestamp 大于 本地实例的lastDirtyTimestamp 。则更新
                    if (replicaDirtyTimestamp > info.getLastDirtyTimestamp()) {
                        info.setLastDirtyTimestamp(replicaDirtyTimestamp);
                    }
                    //设置为actionType为modified
                    info.setActionType(ActionType.MODIFIED);
                    //加入到recentlyChangedQueue 
                    recentlyChangedQueue.add(new RecentlyChangedItem(lease));
                    //更新实例的lastUpdatedTimestamp
                    info.setLastUpdatedTimestamp();
                    //清空readWriteCacheMap对应服务的缓存信息
                    invalidateCache(appName, info.getVIPAddress(), info.getSecureVipAddress());
                }
                return true;
            }
        } finally {
            read.unlock();
        }
    }
    @Override
    public boolean cancel(String appName, String id, boolean isReplication) {
        return internalCancel(appName, id, isReplication);
    }
    protected boolean internalCancel(String appName, String id, boolean isReplication) {
        read.lock();
        try {
            CANCEL.increment(isReplication);
            //根据服务名称获取服务列表实例
            Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
            Lease<InstanceInfo> leaseToCancel = null;
            if (gMap != null) {
            	//从gMap移除该实例
                leaseToCancel = gMap.remove(id);
            }
            recentCanceledQueue.add(new Pair<Long, String>(System.currentTimeMillis(), appName + "(" + id + ")"));
            //从overriddenInstanceStatusMap移除该实例
            InstanceStatus instanceStatus = overriddenInstanceStatusMap.remove(id);
            if (instanceStatus != null) {
                logger.debug("Removed instance id {} from the overridden map which has value {}", id, instanceStatus.name());
            }
            if (leaseToCancel == null) {
                CANCEL_NOT_FOUND.increment(isReplication);
                logger.warn("DS: Registry: cancel failed because Lease is not registered for: {}/{}", appName, id);
                return false;
            } else {
            	//更新evictionTimestamp
                leaseToCancel.cancel();
                InstanceInfo instanceInfo = leaseToCancel.getHolder();
                String vip = null;
                String svip = null;
                if (instanceInfo != null) {
                	//设置actionType
                    instanceInfo.setActionType(ActionType.DELETED);
                    //加入到recentlyChangedQueue中
                    recentlyChangedQueue.add(new RecentlyChangedItem(leaseToCancel));
                    //设置lastUpdatedTimestamp
                    instanceInfo.setLastUpdatedTimestamp();
                    vip = instanceInfo.getVIPAddress();
                    svip = instanceInfo.getSecureVipAddress();
                }
                //清空readWriteCacheMap对应服务的缓存信息
                invalidateCache(appName, vip, svip);
                logger.info("Cancelled instance {}/{} (replication={})", appName, id, isReplication);
            }
        } finally {
            read.unlock();
        }

        synchronized (lock) {
            if (this.expectedNumberOfClientsSendingRenews > 0) {
                //实例剔除了 expectedNumberOfClientsSendingRenews 减一
                this.expectedNumberOfClientsSendingRenews = this.expectedNumberOfClientsSendingRenews - 1;
                //重新设置 服务端期望每分钟接受到的心跳续约的次数
                updateRenewsPerMinThreshold();
            }
        }

        return true;
    }

ApplicationsResource

	//客户端获取服务列表信息(全量)
	@GET
    public Response getContainers(@PathParam("version") String version,
                                  @HeaderParam(HEADER_ACCEPT) String acceptHeader,
                                  @HeaderParam(HEADER_ACCEPT_ENCODING) String acceptEncoding,
                                  @HeaderParam(EurekaAccept.HTTP_X_EUREKA_ACCEPT) String eurekaAccept,
                                  @Context UriInfo uriInfo,
                                  @Nullable @QueryParam("regions") String regionsStr) {

        //省略部分代码
		//构建cacheKey 从 缓存map中获取值 (readOnlyCacheMap,readWriteCacheMap)
        Key cacheKey = new Key(Key.EntityType.Application,
        		//全量
                ResponseCacheImpl.ALL_APPS,
                keyType, CurrentRequestVersion.get(), EurekaAccept.fromString(eurekaAccept), regions
        );

        Response response;
        //是否接受响应结果进行压缩
        if (acceptEncoding != null && acceptEncoding.contains(HEADER_GZIP_VALUE)) {
        	//responseCache.getGZIP(cacheKey)获取服务信息
            response = Response.ok(responseCache.getGZIP(cacheKey))
                    .header(HEADER_CONTENT_ENCODING, HEADER_GZIP_VALUE)
                    .header(HEADER_CONTENT_TYPE, returnMediaType)
                    .build();
        } else {
            response = Response.ok(responseCache.get(cacheKey))
                    .build();
        }
        CurrentRequestVersion.remove();
        return response;
    }
    //客户端获取服务列表信息(增量)
    @Path("delta")
    @GET
    public Response getContainerDifferential(
            @PathParam("version") String version,
            @HeaderParam(HEADER_ACCEPT) String acceptHeader,
            @HeaderParam(HEADER_ACCEPT_ENCODING) String acceptEncoding,
            @HeaderParam(EurekaAccept.HTTP_X_EUREKA_ACCEPT) String eurekaAccept,
            @Context UriInfo uriInfo, @Nullable @QueryParam("regions") String regionsStr) {

        //省略部分代码
        
        Key cacheKey = new Key(Key.EntityType.Application,
        		//增量
                ResponseCacheImpl.ALL_APPS_DELTA,
                keyType, CurrentRequestVersion.get(), EurekaAccept.fromString(eurekaAccept), regions
        );

        final Response response;
		
        if (acceptEncoding != null && acceptEncoding.contains(HEADER_GZIP_VALUE)) {
             response = Response.ok(responseCache.getGZIP(cacheKey))
                    .header(HEADER_CONTENT_ENCODING, HEADER_GZIP_VALUE)
                    .header(HEADER_CONTENT_TYPE, returnMediaType)
                    .build();
        } else {
            response = Response.ok(responseCache.get(cacheKey)).build();
        }

        CurrentRequestVersion.remove();
        return response;
    }

ResponseCacheImpl

	public byte[] getGZIP(Key key) {
		//获取服务列表信息
        Value payload = getValue(key, shouldUseReadOnlyResponseCache);
        if (payload == null) {
            return null;
        }
        //压缩
        return payload.getGzipped();
    }
    @VisibleForTesting
    //该方法细节看到上一篇文章
    //从缓存map中获取到服务列表信息返回
    Value getValue(final Key key, boolean useReadOnlyCache) {
        Value payload = null;
        try {
            if (useReadOnlyCache) {
                final Value currentPayload = readOnlyCacheMap.get(key);
                if (currentPayload != null) {
                    payload = currentPayload;
                } else {
                    payload = readWriteCacheMap.get(key);
                    readOnlyCacheMap.put(key, payload);
                }
            } else {
                payload = readWriteCacheMap.get(key);
            }
        } catch (Throwable t) {
            logger.error("Cannot get value for key : {}", key, t);
        }
        return payload;
    }

InstanceResource

	//服务实例心跳续约
	@PUT
    public Response renewLease(
            @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
            @QueryParam("overriddenstatus") String overriddenStatus,
            @QueryParam("status") String status,
            @QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
        //是否为其他eureka节点同步过来的信息
        boolean isFromReplicaNode = "true".equals(isReplication);
        //服务续约
        boolean isSuccess = registry.renew(app.getName(), id, isFromReplicaNode);
		
		
        if (!isSuccess) {
            logger.warn("Not Found (Renew): {} - {}", app.getName(), id);
           	//返回 NOT_FOUND 404 , 客户端收到该状态码则重新调用服务端注册流程
            return Response.status(Status.NOT_FOUND).build();
        }
        // Check if we need to sync based on dirty time stamp, the client
        // instance might have changed some value
        Response response;
        //syncWhenTimestampDiffers默认为true
        if (lastDirtyTimestamp != null && serverConfig.shouldSyncWhenTimestampDiffers()) {
            response = this.validateDirtyTimestamp(Long.valueOf(lastDirtyTimestamp), isFromReplicaNode);
            // Store the overridden status since the validation found out the node that replicates wins
            if (response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()
                    && (overriddenStatus != null)
                    && !(InstanceStatus.UNKNOWN.name().equals(overriddenStatus))
                    && isFromReplicaNode) {
                registry.storeOverriddenStatusIfRequired(app.getAppName(), id, InstanceStatus.valueOf(overriddenStatus));
            }
        } else {
            response = Response.ok().build();
        }
        logger.debug("Found (Renew): {} - {}; reply status={}", app.getName(), id, response.getStatus());
        return response;
    }
    private Response validateDirtyTimestamp(Long lastDirtyTimestamp,
                                            boolean isReplication) {
        //根据服务名称和实例id获取到实例
        InstanceInfo appInfo = registry.getInstanceByAppAndId(app.getName(), id, false);
        //lastDirtyTimestamp(实例最后一次被修改的时间)
        if (appInfo != null) {
        	//如果 本次续约携带的lastDirtyTimestamp 和 实例的lastDirtyTimestamp 不一致,正常情况下一致。
            if ((lastDirtyTimestamp != null) && (!lastDirtyTimestamp.equals(appInfo.getLastDirtyTimestamp()))) {
                Object[] args = {id, appInfo.getLastDirtyTimestamp(), lastDirtyTimestamp, isReplication};
				
				//本次续约携带的lastDirtyTimestamp 晚于 实例的LastDirtyTimestamp
                if (lastDirtyTimestamp > appInfo.getLastDirtyTimestamp()) {
                    logger.debug(
                            "Time to sync, since the last dirty timestamp differs -"
                                    + " ReplicationInstance id : {},Registry : {} Incoming: {} Replication: {}",
                            args);
                    //返回 NOT_FOUND 404,
                    return Response.status(Status.NOT_FOUND).build();
                } 
                //本次续约携带的lastDirtyTimestamp 早于 实例的lastDirtyTimestamp  
                else if (appInfo.getLastDirtyTimestamp() > lastDirtyTimestamp) {
                    // In the case of replication, send the current instance info in the registry for the
                    // replicating node to sync itself with this one.
                    //如果是被其他eureka节点同步过来的信息
                    if (isReplication) {
                        logger.debug(
                                "Time to sync, since the last dirty timestamp differs -"
                                        + " ReplicationInstance id : {},Registry : {} Incoming: {} Replication: {}",
                                args);
                         // 返回CONFLICT 409 。 返回了appInfo(该节点的实例的数据信息) 给原本主动同步的eureka节点
                        return Response.status(Status.CONFLICT).entity(appInfo).build();
                    } else {
                        return Response.ok().build();
                    }
                }
            }

        }
        return Response.ok().build();
    }
    //服务状态变更
    @PUT
    @Path("status")
    public Response statusUpdate(
            @QueryParam("value") String newStatus,
            @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
            @QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
        try {
        	//使用服务名称和实例id获取实例
        	//判断实例是否存在
            if (registry.getInstanceByAppAndId(app.getName(), id) == null) {
                logger.warn("Instance not found: {}/{}", app.getName(), id);
                return Response.status(Status.NOT_FOUND).build();
            }
            //实例状态更新
            boolean isSuccess = registry.statusUpdate(app.getName(), id,
                    InstanceStatus.valueOf(newStatus), lastDirtyTimestamp,
                    "true".equals(isReplication));

            if (isSuccess) {
                logger.info("Status updated: {} - {} - {}", app.getName(), id, newStatus);
                return Response.ok().build();
            } else {
                logger.warn("Unable to update status: {} - {} - {}", app.getName(), id, newStatus);
                return Response.serverError().build();
            }
        } catch (Throwable e) {
            logger.error("Error updating instance {} for status {}", id,
                    newStatus);
            return Response.serverError().build();
        }
    }
    //服务剔除
    @DELETE
    public Response cancelLease(
            @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
        try {     
            boolean isSuccess = registry.cancel(app.getName(), id,
                "true".equals(isReplication));

            if (isSuccess) {
                logger.debug("Found (Cancel): {} - {}", app.getName(), id);
                return Response.ok().build();
            } else {
                logger.info("Not Found (Cancel): {} - {}", app.getName(), id);
                return Response.status(Status.NOT_FOUND).build();
            }
        } catch (Throwable e) {
            logger.error("Error (cancel): {} - {}", app.getName(), id, e);
            return Response.serverError().build();
        }

    }

看下同步给其他eureka节点失败的处理(非IoException,ReplicationTaskProcessor会对网络通信异常返回ProcessingResult.Congestion或者ProcessingResult.TransientError,然后重新提交任务到队列中)。
PeerEurekaNode,心跳续约操作还重写了handleFailure做了额外的操作。

	public void heartbeat(final String appName, final String id,
                          final InstanceInfo info, final InstanceStatus overriddenStatus,
                          boolean primeConnection) throws Throwable {
       	//省略部分代码
        ReplicationTask replicationTask = new InstanceReplicationTask(targetHost, Action.Heartbeat, info, overriddenStatus, false) {
            @Override
            public EurekaHttpResponse<InstanceInfo> execute() throws Throwable {
                return replicationClient.sendHeartBeat(appName, id, info, overriddenStatus);
            }
			
			//心跳续约同步到eureka其他节点失败
            @Override
            public void handleFailure(int statusCode, Object responseEntity) throws Throwable {
                super.handleFailure(statusCode, responseEntity);
                //如果为404
                if (statusCode == 404) {
                    logger.warn("{}: missing entry.", getTaskName());
                    if (info != null) {
                        logger.warn("{}: cannot find instance id {} and hence replicating the instance with status {}",
                                getTaskName(), info.getId(), info.getStatus());
                        //向该失败的eureka节点,重新发送客户端注册请求。
                        register(info);
                    }
                } 
                //SyncWhenTimestampDiffers默认为true
                else if (config.shouldSyncWhenTimestampDiffers()) {
                    InstanceInfo peerInstanceInfo = (InstanceInfo) responseEntity;
                    if (peerInstanceInfo != null) {
                    	//使用返回状态码非404的eureka节点发送回来的peerInstanceInfo(实例信息)更新本地的实例数据
                        syncInstancesIfTimestampDiffers(appName, id, info, peerInstanceInfo);
                    }
                }
            }
        };
		//省略部分代码
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值