Eureka 客户端启动时如何注册到服务端?
1 个回答
杯中之物从来不能消愁补过格列柯南1、源码分析 Eureka客户端在启动后,会创建一些定时任务,其中就有一个任务heartbeatExecutor就是就是处理心跳的线程池,部分源码(源码位置:com.netflix.discovery.DiscoveryClient)如下: ```java heartbeatExecutor = new ThreadPoolExecutor( 1, clientConfig.getHeartbeatExecutorThreadPoolSize(), 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadFactoryBuilder() .setNameFormat("DiscoveryClient-HeartbeatExecutor-%d") .setDaemon(true) .build() ); // use direct handoff //...此处省略其他代码 //finally, init the schedule tasks (e.g. cluster resolvers, heartbeat, instanceInfo replicator, fetch initScheduledTasks(); ``` 查看方法initScheduledTasks以及注释,可知该方法是初始化所有的任务(schedule tasks)。 ```java /** * Initializes all scheduled tasks. */ private void initScheduledTasks() { ... // Heartbeat timer scheduler.schedule( new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() ), renewalIntervalInSecs, TimeUnit.SECONDS); ... } ``` 上述方法中,第15行创建了一个线程HeartbeatThread,该线程就是处理心跳任务: ```java /** * The heartbeat task that renews the lease in the given intervals. */ private class HeartbeatThread implements Runnable { public void run() { if (renew()) { lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis(); } } } /** * Renew with the eureka service by making the appropriate REST call */ boolean renew() { EurekaHttpResponse<InstanceInfo> httpResponse; try { httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null); logger.debug(PREFIX + "{} - Heartbeat status: {}", appPathIdentifier, httpResponse.getStatusCode()); if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) { REREGISTER_COUNTER.increment(); logger.info(PREFIX + "{} - Re-registering apps/{}", appPathIdentifier, instanceInfo.getAppName()); long timestamp = instanceInfo.setIsDirtyWithTime(); boolean success = register(); if (success) { instanceInfo.unsetIsDirty(timestamp); } return success; } return httpResponse.getStatusCode() == Status.OK.getStatusCode(); } catch (Throwable e) { logger.error(PREFIX + "{} - was unable to send heartbeat!", appPathIdentifier, e); return false; } } ``` 在renew方法中,首先会发送一个心跳数据到服务端,服务端返回一个状态码,如果是NOT_FOUND(即404),表示Eureka服务端不存在该客户端的服务信息,那么就会向服务端发起注册请求(上面代码25行调用register方法): ```java boolean register() throws Throwable { logger.info(PREFIX + "{}: registering service...", appPathIdentifier); EurekaHttpResponse<Void> httpResponse; try { httpResponse = eurekaTransport.registrationClient.register(instanceInfo); } catch (Exception e) { logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e); throw e; } if (logger.isInfoEnabled()) { logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode()); } return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode(); } ``` 在register方法中,向服务端的注册信息instanceInfo,它是com.netflix.appinfo.InstanceInfo,包括服务名、ip、端口、唯一实例ID等信息。 ### 2、总结 Eureka客户端在启动时,首先会创建一个心跳的定时任务,定时向服务端发送心跳信息,服务端会对客户端心跳做出响应,如果响应状态码为404时,表示服务端没有该客户端的服务信息,那么客户端则会向服务端发送注册请求,注册信息包括服务名、ip、端口、唯一实例ID等信息。编辑于 2022-03-11 20:43 •IP属地 福建举报评论收藏
公众号进入网站体验更佳

