2023-09-15
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105613789

服务注册和续约的大致流程

202309152310473911.png
先说下服务注册吧,毕竟作为一个提供服务的客户端,注册到注册中心去比较重要,也是第一步。

InstanceInfoReplicator的run

这个就是注册服务的调度方法,首次延迟30秒执行,后面可能会调整。所以严格说他不是一个定时的任务,只是可调节的定时的调度任务。首先进行客户端实例信息刷新,然后看是否有状态改变,有贵爱彼岸的话dirtyTimestamp不为空,有改变就要通知注册中心,所以要去注册,完成之后继续调度任务。

        public void run() {
            try {
                discoveryClient.refreshInstanceInfo();//刷新实例信息
    
                Long dirtyTimestamp = instanceInfo.isDirtyWithTime();//是否有状态更新过了,有的话获取更新的时间
                if (dirtyTimestamp != null) {//有脏数据,要重新注册
                    discoveryClient.register();
                    instanceInfo.unsetIsDirty(dirtyTimestamp);//设置更新标记为不更新
                }
            } catch (Throwable t) {
                logger.warn("There was a problem with the instance info replicator", t);
            } finally {
                Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
                scheduledPeriodicRef.set(next);
            }
        }

DiscoveryClient的refreshInstanceInfo

这里主要的是刷新状态信息,根据HealthCheckHandler去获取当前实例的状态信息,然后进行设置。

        void refreshInstanceInfo() {
            applicationInfoManager.refreshDataCenterInfoIfRequired();//刷新数据中心,和AWS亚马逊云有关
            applicationInfoManager.refreshLeaseInfoIfRequired();//更新租约信息
    
            InstanceStatus status;
            try {//获取实例状态
                status = getHealthCheckHandler().getStatus(instanceInfo.getStatus());
            } catch (Exception e) {
                logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", e);
                status = InstanceStatus.DOWN;
            }
    
            if (null != status) {
                applicationInfoManager.setInstanceStatus(status);
            }
        }

ApplicationInfoManager的setInstanceStatus

主要是这里,首先获取新的状态,然后设置到实例中,内部会有判断,如果是新的就设置标记,返回先前的状态,如果有改变就要进行通知。

      public synchronized void setInstanceStatus(InstanceStatus status) {
            InstanceStatus next = instanceStatusMapper.map(status);//获取下一个新状态
            if (next == null) {
                return;
            }
            //如果状态有改变,会返回先前状态,否则就是null
            InstanceStatus prev = instanceInfo.setStatus(next);
            if (prev != null) {//有改变了才广播
                for (StatusChangeListener listener : listeners.values()) {
                    try {
                        listener.notify(new StatusChangeEvent(prev, next));
                    } catch (Exception e) {
                        logger.warn("failed to notify listener: {}", listener.getId(), e);
                    }
                }
            }
        }

InstanceInfo的setStatus

设置信息,如果是新的就设置更新标记,isInstanceInfoDirty=true,返回先前的状态。

        public synchronized InstanceStatus setStatus(InstanceStatus status) {
            if (this.status != status) {
                InstanceStatus prev = this.status;
                this.status = status;
                setIsDirty();//设置状态更新
                return prev;
            }
            return null;
        }
        public synchronized void setIsDirty() {
            isInstanceInfoDirty = true;
            lastDirtyTimestamp = System.currentTimeMillis();
        }

DiscoveryClient的状态改变事件监听

前面忘记说了DiscoveryClient初始化的时候还创建了一个监听器,监听实例状态改变,如果有改变不为DOWN的话,就会调用instanceInfoReplicator.onDemandUpdate();

202309152310482472.png

InstanceInfoReplicator的onDemandUpdate

其实这个就是又提交了一个服务注册的任务,里面还是调用InstanceInfoReplicatorrun,把前一个任务取消掉,因为这个scheduler只有一个线程核心线程在执行任务队列的任务,所以前一个任务被取消了,不会循环调度,就只有一个新提交的任务会循环调度。

     public boolean onDemandUpdate() {
            if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {//满足频率
                if (!scheduler.isShutdown()) {
                    scheduler.submit(new Runnable() {//提交新任务
                        @Override
                        public void run() {
                            logger.debug("Executing on-demand update of local InstanceInfo");
        
                            Future latestPeriodic = scheduledPeriodicRef.get();//获取最近的一次任务
                            if (latestPeriodic != null && !latestPeriodic.isDone()) {//如果没完成
                                logger.debug("Canceling the latest scheduled update, it will be rescheduled at the end of on demand update");
                                latestPeriodic.cancel(false);//取消,非强制中断
                            }
        
                            InstanceInfoReplicator.this.run();//启动
                        }
                    });
                    return true;
                } else {
                    logger.warn("Ignoring onDemand update due to stopped scheduler");
                    return false;
                }
            } else {
                logger.warn("Ignoring onDemand update due to rate limiter");
                return false;
            }
        }

DiscoveryClient的register

任务执行到这里的时候,会发现dirtyTimestamp不为空了,因为状态被改过了,所以可以进行想注册中心注册了。

202309152310490493.png
isInstanceInfoDirty已经是true了。

        public synchronized Long isDirtyWithTime() {
            if (isInstanceInfoDirty) {
                return lastDirtyTimestamp;
            } else {
                return null;
            }
        }

202309152310495094.png
内部最后就是JerseyApplicationClientpost方法。

202309152310501455.png
注册完了再清楚状态,继续调度。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

阅读全文