【Eureka】【源码+图解】【六】Eureka的续约功能

阅读: 评论:0

【Eureka】【源码+图解】【六】Eureka的续约功能

【Eureka】【源码+图解】【六】Eureka的续约功能

【Eureka】【源码+图解】【五】Eureka的注册功能

目录

  • 5. 续约
    • 5.1 初始化
    • 5.2 TimedSupervisorTask
    • 5.3 renew()
    • 5.4 服务端收到renew请求
    • 5.5 服务端更新实例续约信息
    • 5.6 同步到其他server节点

5. 续约

先看下整体流程


接下来分析绿色的6个步骤

5.1 初始化

public class DiscoveryClient implements EurekaClient {private final ThreadPoolExecutor heartbeatExecutor;private TimedSupervisorTask heartbeatTask;DiscoveryClient(...) {// 1. 创建续约线程池heartbeatExecutor = new ThreadPoolExecutor(1, // eureka.client.heartbeatExecutorThreadPoolSize,默认HeartbeatExecutorThreadPoolSize(), 0, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),new ThreadFactoryBuilder().setNameFormat("DiscoveryClient-HeartbeatExecutor-%d").setDaemon(true).build());}private void initScheduledTasks() {if (clientConfig.shouldRegisterWithEureka()) {// eureka.instance.leaseRenewalIntervalInSeconds,续约间隔,默认30int renewalIntervalInSecs = LeaseInfo().getRenewalIntervalInSecs();// eureka.client.heartbeatExecutorExponentialBackOffBound,默认10int expBackOffBound = HeartbeatExecutorExponentialBackOffBound();// 2. 包装成定时任务heartbeatTask = new TimedSupervisorTask("heartbeat",scheduler,heartbeatExecutor,renewalIntervalInSecs,TimeUnit.SECONDS,expBackOffBound,new HeartbeatThread() // 续约的真正逻辑);// 3. 开启定时任务scheduler.schedule(heartbeatTask,renewalIntervalInSecs, TimeUnit.SECONDS);}}
}

5.2 TimedSupervisorTask

public class TimedSupervisorTask extends TimerTask {@Overridepublic void run() {Future<?> future = null;try {// 提交续约task到线程池future = executor.submit(task);// 阻塞等待直到返回结果或者超时(timeoutMillis, TimeUnit.MILLISECONDS);// 下一次延时任务的时间delay.set(timeoutMillis);} catch (TimeoutException e) {// 等待结果超时,指数级增长超时时间// 第一次:currentDelay// 第二次:currentDelay * 2// ...// 第n+1次:currentDelay * 2^n// currentDelay * 2^n 必须小于eureka.instance.leaseRenewalIntervalInSeconds * eureka.client.heartbeatExecutorExponentialBackOffBound// 否则取两者间最小值timeoutCounter.increment();long currentDelay = ();long newDelay = Math.min(maxDelay, currentDelay * 2);delaypareAndSet(currentDelay, newDelay);} catch (RejectedExecutionException e) {rejectedCounter.increment();} catch (Throwable e) {throwableCounter.increment();} finally {if (future != null) {future.cancel(true);}if (!scheduler.isShutdown()) {// 定时下一次续约时间scheduler.schedule(this, (), TimeUnit.MILLISECONDS);}}}
}

5.3 renew()

HeartbeatThread获得线程资源,执行run()方法

public class DiscoveryClient implements EurekaClient {private class HeartbeatThread implements Runnable {public void run() {// 执行续约请求if (renew()) {lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();}}}boolean renew() {EurekaHttpResponse<InstanceInfo> httpResponse;try {// 发送续约请求httpResponse = istrationClient.AppName(), Id(), instanceInfo, null);if (StatusCode() == Status.StatusCode()) {// 续约失败,重新注册boolean success = register();......return success;}StatusCode() == StatusCode();} catch (Throwable e) {(PREFIX + "{} - was unable to send heartbeat!", appPathIdentifier, e);return false;}}
}

5.4 服务端收到renew请求

public class InstanceResource {@PUTpublic Response renewLease(@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,@QueryParam("overriddenstatus") String overriddenStatus,@QueryParam("status") String status,@QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {// 客户端发过来的请求为false,需要同步到其他server节点boolean isFromReplicaNode = "true".equals(isReplication);boolean isSuccess = Name(), id, isFromReplicaNode);......return response;}
}

5.5 服务端更新实例续约信息

public abstract class AbstractInstanceRegistry implements InstanceRegistry {public boolean renew(String appName, String id, boolean isReplication) {// 1. 获取实例所属的应用Map<String, Lease<InstanceInfo>> gMap = (appName);Lease<InstanceInfo> leaseToRenew = null;// 2. 获取旧的实例信息if (gMap != null) {leaseToRenew = (id);}if (leaseToRenew == null) {return false;} else {InstanceInfo instanceInfo = Holder();if (instanceInfo != null) {// 3. 更新statusInstanceStatus overriddenInstanceStatus = OverriddenInstanceStatus(instanceInfo, leaseToRenew, isReplication);if (overriddenInstanceStatus == InstanceStatus.UNKNOWN) {return false;}if (!Status().equals(overriddenInstanceStatus)) {instanceInfo.setStatusWithoutDirty(overriddenInstanceStatus);}}renewsLastMin.increment();// 4. 更新lastUpdateTimestamp以便服务端服务剔除时检查检查w();return true;}}// 获取实例的更新状态protected InstanceInfo.InstanceStatus getOverriddenInstanceStatus(InstanceInfo r,Lease<InstanceInfo> existingLease,boolean isReplication) {// InstanceStatus: UP, DOWN, STARTING, OUT_OF_SERVICE, UNKNOWN;InstanceStatusOverrideRule rule = new FirstMatchWinsCompositeRule(// 如果r是UP or OUT_OF_SERVICE,继续往下判断;否则返回相应的值new DownOrStartingRule(),  // 如果r不在overriddenInstanceStatusMap中继续往下判断,否则返回相应值new OverrideExistsRule(overriddenInstanceStatusMap), // 如果existingLease不为空且其值都不是UP or OUT_OF_SERVICE继续往下判断,否则返回相应的值new LeaseExistsRule(), // 返回r的statusnew AlwaysMatchInstanceStatusRule());return rule.apply(r, existingLease, isReplication).status();}
}

5.6 同步到其他server节点

public class PeerAwareInstanceRegistryImpl extends AbstractInstanceRegistry implements PeerAwareInstanceRegistry {public boolean renew(final String appName, final String id, final boolean isReplication) {if (w(appName, id, isReplication)) {// 复制到其他server节点,后面的除了Action.Heartbeat,其他的与register相同,参考4.7节replicateToPeers(Action.Heartbeat, appName, id, null, null, isReplication);return true;}return false;}
}

Eureka的续约功能整体流程就讲完了。

未完待续

本文发布于:2024-01-31 01:16:19,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170663498224293.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:源码   功能   Eureka
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23