摘要:在本篇文章中主要对Eureka的Cancel(服务下线)进行源码分析,在Service Provider服务shut down的时候,需要及时通知Eureka Server把自己剔除,从而避免其它客户端调用已经下线的服务,导致服务不可用。
Cancel(服务下线)
概述
在Service Provider服务shut down的时候,需要及时通知Eureka Server把自己剔除,从而避免客户端调用已经下线的服务。
服务提供者端源码分析
- 在eureka-client-1.4.1中的com.netflix.discovery.DiscoveryClient中shutdown()的
867
行。123456789101112131415161718192021222324252627282930313233/*** Shuts down Eureka Client. Also sends a deregistration request to the* eureka server.*/public synchronized void shutdown() {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()
的方法是服务下线的入口
- 在eureka-client-1.4.1中的
com.netflix.discovery.DiscoveryClient
中unregister()
的897
行12345678910111213141516/*** unregister w/ the eureka service.*/void unregister() {// 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服务下线实现细节
在
com.netflix.eureka.resources.InstanceResource
中的280
行中的cancelLease()
方法123456789101112131415public Response cancelLease(@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {//调用cancelboolean 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();}}在
org.springframework.cloud.netflix.eureka.server.InstanceRegistry
中的95
行的cancel()
方法,123456public boolean cancel(String appName, String serverId, boolean isReplication) {handleCancelation(appName, serverId, isReplication);//调用父类中的cancelreturn super.cancel(appName, serverId, isReplication);}在
com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl
中的376
行123456789101112131415161718public boolean cancel(final String appName, final String id,final boolean isReplication) {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());}}return true;}return false;}
4.在com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl中的618
行,主要接口实现方式和register基本一致:首先更新自身Eureka Server中服务的状态,再同步到其它Eureka Server中。
至此,Eureka服务续约源码分析结束,大家有兴趣可自行阅读。
源码分析链接
其它源码分析链接:
Spring Cloud中@EnableEurekaClient源码分析:
http://xujin.org/sc/sc-enableEurekaClient-annonation/
Spring Cloud Eureka服务注册源码分析:
http://xujin.org/sc/sc-eureka-register/
Spring Cloud Eureka服务续约(Renew)源码分析
http://xujin.org/sc/sc-eureka-renew/