Spring Cloud Eureka服务下线(Cancel)源码分析

摘要:在本篇文章中主要对Eureka的Cancel(服务下线)进行源码分析,在Service Provider服务shut down的时候,需要及时通知Eureka Server把自

摘要:在本篇文章中主要对Eureka的Cancel(服务下线)进行源码分析,在Service Provider服务shut down的时候,需要及时通知Eureka Server把自己剔除,从而避免其它客户端调用已经下线的服务,导致服务不可用。

Cancel(服务下线)

概述

在Service Provider服务shut down的时候,需要及时通知Eureka Server把自己剔除,从而避免客户端调用已经下线的服务。

服务提供者端源码分析

  1. 在eureka-client-1.4.1中的com.netflix.discovery.DiscoveryClient中shutdown()的 867行,
    /** * Shuts down Eureka Client. Also sends a deregistration request to the * eureka server. */@PreDestroy@Overridepublicsynchronizedvoidshutdown(){if(isShutdown.compareAndSet(false,true)) { logger.info("Shutting down DiscoveryClient ...");if(statusChangeListener !=null&& applicationInfoManager !=null) { applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId()); } cancelScheduledTasks();// If APPINFO was registeredif(applicationInfoManager !=null&& clientConfig.shouldRegisterWithEureka()) { applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);//调用下线接口 unregister(); }if(eurekaTransport !=null) { eurekaTransport.shutdown(); } heartbeatStalenessMonitor.shutdown(); registryStalenessMonitor.shutdown(); logger.info("Completed shut down of DiscoveryClient"); } }

Tips @PreDestroy注解或 shutdown()的方法是服务下线的入口

  1. 在eureka-client-1.4.1中的 com.netflix.discovery.DiscoveryClientunregister()897
    /** * unregister w/ the eureka service. */voidunregister(){// It can be null if shouldRegisterWithEureka == falseif(eurekaTransport !=null&& eurekaTransport.registrationClient !=null) {try{ logger.info("Unregistering ...");//发送服务下线请求 EurekaHttpResponse<Void> httpResponse = eurekaTransport.registrationClient.cancel(instanceInfo.getAppName(), instanceInfo.getId()); logger.info(PREFIX + appPathIdentifier + " - deregister status: "+ httpResponse.getStatusCode()); } catch(Exception e) { logger.error(PREFIX + appPathIdentifier + " - de-registration failed"+ e.getMessage(), e); } }}

Eureka Server服务下线实现细节

  1. com.netflix.eureka.resources.InstanceResource中的 280行中的 cancelLease()方法

    @DELETEpublicResponsecancelLease( @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {//调用cancelbooleanisSuccess = registry.cancel(app.getName(), id,"true".equals(isReplication));if(isSuccess) { logger.debug("Found (Cancel): "+ app.getName() +" - "+ id);returnResponse.ok().build(); } else{ logger.info("Not Found (Cancel): "+ app.getName() +" - "+ id);returnResponse.status(Status.NOT_FOUND).build(); }}
  2. org.springframework.cloud.netflix.eureka.server.InstanceRegistry中的 95行的 cancel()方法,

    @Overridepublicbooleancancel(String appName, String serverId,booleanisReplication){ handleCancelation(appName, serverId, isReplication);//调用父类中的cancelreturnsuper.cancel(appName, serverId, isReplication);}
  3. com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl中的 376

    @Overridepublicbooleancancel(finalString appName,finalString id,finalbooleanisReplication) {if(super.cancel(appName, id, isReplication)) {//服务下线成功后,同步更新信息到其它Eureka Server节点 replicateToPeers(Action.Cancel, appName, id, null,null, isReplication);synchronized(lock) {if(this.expectedNumberOfRenewsPerMin >0) {// Since the client wants to cancel it, reduce the threshold (1 for 30 seconds, 2 for a minute)this.expectedNumberOfRenewsPerMin =this.expectedNumberOfRenewsPerMin -2;this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()); } }returntrue; }returnfalse;}
  4. replicateToPeers(Action.Heartbeat, appName, id, null, null, isReplication);调用自身的 replicateToPeers()方法,在com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl中的 618行,主要接口实现方式和register基本一致:首先更新自身Eureka Server中服务的状态,再同步到其它Eureka Server中。

    privatevoidreplicateToPeers(Action action, String appName, String id, InstanceInfo info /* optional */, InstanceStatus newStatus /* optional */,booleanisReplication) { Stopwatch tracer = action.getTimer().start();try{if(isReplication) { numberOfReplicationsLastMin.increment(); }// If it is a replication already, do not replicate again as this will create a poison replicationif(peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {return; }// 同步把续约信息同步到其它的Eureka Server中for(finalPeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {// If the url represents this host, do not replicate to yourself.if(peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {continue; }//根据action做相应操作的同步 replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node); } } finally{ tracer.stop(); } }

至此,Eureka服务续约源码分析结束,大家有兴趣可自行阅读。

未登录用户
全部评论0
到底啦