SpringCloud源码剖析-Eureka Server服务下线

简介: 1.从registry中移除服务,2.从overriddenInstanceStatusMap状态map中移除服务状态3.添加到最近取消队列4.调用Lease.cancel方法,将租约对象中的逐出时间修改为当前时间5.修改服务的InstanceInfo的状态为DELETE6.添加到最近修改队列7.更新服务最后修改时间8.使ReponseCache缓存无

Eureka Server 服务下线

在《Eureka Client取消注册》中我们有分析到,当Eureka Client 客户端当服务关闭,触发客户端服务下线方法,客户端执行一系列下线逻辑后会向Eureka Server服务端发送服务下线请求,服务端处理下线的请求是在com.netflix.eureka.resources.InstanceResource#cancelLease方法中

/**处理此特定实例的租赁取消* Handles cancellation of leases for this particular instance.** @param isReplication*            a header parameter containing information whether this is*            replicated from other nodes.* @return response indicating whether the operation was a success or*         failure.*/@DELETEpublicResponsecancelLease(
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) StringisReplication) {
try {
//调用 InstanceRegistry的 cancel 方法下线服务booleanisSuccess=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();
        }
    } catch (Throwablee) {
logger.error("Error (cancel): {} - {}", app.getName(), id, e);
returnResponse.serverError().build();
    }
}

InstanceRegistry的 cancel 方法

publicclassInstanceRegistryextendsPeerAwareInstanceRegistryImplimplementsApplicationContextAware {
@Overridepublicbooleancancel(StringappName, StringserverId, booleanisReplication) {
//抛出EurekaInstanceCanceledEvent取消事件handleCancelation(appName, serverId, isReplication);
//调用PeerAwareInstanceRegistryImpl#cancelreturnsuper.cancel(appName, serverId, isReplication);
   }
//抛出EurekaInstanceCanceledEvent取消事件privatevoidhandleCancelation(StringappName, Stringid, booleanisReplication) {
log("cancel "+appName+", serverId "+id+", isReplication "+isReplication);
publishEvent(newEurekaInstanceCanceledEvent(this, appName, id, isReplication));
   }

这里比较简单,抛出EurekaInstanceCanceledEvent时间后调用super(PeerAwareInstanceRegistryImpl)的下线方法

/** (non-Javadoc)** @see com.netflix.eureka.registry.InstanceRegistry#cancel(java.lang.String,* java.lang.String, long, boolean)*/@Overridepublicbooleancancel(finalStringappName, finalStringid,
finalbooleanisReplication) {
//调用super.cancel下线方法:com.netflix.eureka.registry.AbstractInstanceRegistry#cancelif (super.cancel(appName, id, isReplication)) {
//复制到其他的Eureka节点replicateToPeers(Action.Cancel, appName, id, null, null, isReplication);
synchronized (lock) {
if (this.expectedNumberOfRenewsPerMin>0) {
//如果每分钟的预期续订次数大于0//由于客户想取消该阈值,因此降低阈值(1次 30秒,2次 1分钟)// Since the client wants to cancel it, reduce the threshold (1 for 30 seconds, 2 for a minute)//预期续订次数 = 预期续订次数 -2 (2次 1分钟 , 1次 30)this.expectedNumberOfRenewsPerMin=this.expectedNumberOfRenewsPerMin-2;
//续订次数阈值  = 预期续订次数  * 0.85this.numberOfRenewsPerMinThreshold=                    (int) (this.expectedNumberOfRenewsPerMin*serverConfig.getRenewalPercentThreshold());
            }
        }
returntrue;
    }
returnfalse;
}

这里继续调用super.cancel(AbstractInstanceRegistry#cancel),完成下线后重新计算了续约阈值,继续看AbstractInstanceRegistry#cancel方法

publicabstractclassAbstractInstanceRegistryimplementsInstanceRegistry {
/**//取消实例注册//这通常是由客户端调用时关闭通知服务器从流量中除去实例* Cancels the registration of an instance.** <p>* This is normally invoked by a client when it shuts down informing the* server to remove the instance from traffic.* </p>** @param appName the application name of the application.* @param id the unique identifier of the instance.* @param isReplication true if this is a replication event from other nodes, false*                      otherwise.* @return true if the instance was removed from the {@link AbstractInstanceRegistry} successfully, false otherwise.*/@Overridepublicbooleancancel(StringappName, Stringid, booleanisReplication) {
returninternalCancel(appName, id, isReplication);
    }
/**内部取消服务注册* {@link #cancel(String, String, boolean)} method is overridden by {@link PeerAwareInstanceRegistry}, so each* cancel request is replicated to the peers. This is however not desired for expires which would be counted* in the remote peers as valid cancellations, so self preservation mode would not kick-in.*/protectedbooleaninternalCancel(StringappName, Stringid, booleanisReplication) {
try {
//上锁read.lock();
//服务取消数增加CANCEL.increment(isReplication);
//获取当前提出的服务Map<String, Lease<InstanceInfo>>gMap=registry.get(appName);
Lease<InstanceInfo>leaseToCancel=null;
if (gMap!=null) {
//从服务注册的map中移除掉当前服务leaseToCancel=gMap.remove(id);
            }
//添加到最近取消队列synchronized (recentCanceledQueue) {
recentCanceledQueue.add(newPair<Long, String>(System.currentTimeMillis(), appName+"("+id+")"));
            }
//overriddenInstanceStatusMap 服务状态map中移除当前服务InstanceStatusinstanceStatus=overriddenInstanceStatusMap.remove(id);
if (instanceStatus!=null) {
logger.debug("Removed instance id {} from the overridden map which has value {}", id, instanceStatus.name());
            }
if (leaseToCancel==null) {
//没找到服务CANCEL_NOT_FOUND.increment(isReplication);
logger.warn("DS: Registry: cancel failed because Lease is not registered for: {}/{}", appName, id);
returnfalse;
            } else {
//调用Lease.cancel方法leaseToCancel.cancel();
//获取服务实例信息InstanceInfoinstanceInfo=leaseToCancel.getHolder();
Stringvip=null;
Stringsvip=null;
if (instanceInfo!=null) {
//实例状态修改为删除instanceInfo.setActionType(ActionType.DELETED);
//添加最近修改队列recentlyChangedQueue.add(newRecentlyChangedItem(leaseToCancel));
//实例信息对象修改最后修改时间instanceInfo.setLastUpdatedTimestamp();
vip=instanceInfo.getVIPAddress();
svip=instanceInfo.getSecureVipAddress();
                }
//使缓存无效,调用responseCache.invalidate让服务在缓存中失效invalidateCache(appName, vip, svip);
logger.info("Cancelled instance {}/{} (replication={})", appName, id, isReplication);
returntrue;
            }
        } finally {
read.unlock();
        }
    }
}

AbstractInstanceRegistry的cancel方法中调用了internalCancel去取消服务的注册,其实在之间分析服务剔除的时候也嗲用这个方法,方法的逻辑大致是:

  • 1.从registry中移除服务,
  • 2.从overriddenInstanceStatusMap状态map中移除服务状态
  • 3.添加到最近取消队列
  • 4.调用Lease.cancel方法,将租约对象中的逐出时间修改为当前时间
  • 5.修改服务的InstanceInfo的状态为DELETE
  • 6.添加到最近修改队列
  • 7.更新服务最后修改时间
  • 8.使ReponseCache缓存无效

总结

我们发现,Eureka Server服务剔除和服务下线的流程后半截很相似,一个是通过定时任务来实现服务端过期的服务的剔除,一个是客户端发送请求到服务端剔除指定的服务,都是走服务下线逻辑

目录
相关文章
|
6月前
|
负载均衡 算法 Java
【SpringCloud(4)】OpenFeign客户端:OpenFeign服务绑定;调用服务接口;Feign和OpenFeign
Feign是一个WebService客户端。使用Feign能让编写WebService客户端更加简单。 它的使用方法是定义一个服务接口然后再上面添加注解。Feign也支持可拔插式的编码器和解码器。SpringCloud对Feign进行了封装,十七支持了SpringMVC标准注解和HttpMessageConverters。 Feign可用于Eureka和Ribbon组合使用以支持负载均衡
862 140
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
14710 60
|
8月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1245 3
|
6月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
9月前
|
Prometheus 监控 Cloud Native
Docker 部署 Prometheus 和 Grafana 监控 Spring Boot 服务
Docker 部署 Prometheus 和 Grafana 监控 Spring Boot 服务实现步骤
796 0
|
人工智能 自然语言处理 Java
对话即服务:Spring Boot整合MCP让你的CRUD系统秒变AI助手
本文介绍了如何通过Model Context Protocol (MCP) 协议将传统Spring Boot服务改造为支持AI交互的智能系统。MCP作为“万能适配器”,让AI以统一方式与多种服务和数据源交互,降低开发复杂度。文章以图书管理服务为例,详细说明了引入依赖、配置MCP服务器、改造服务方法(注解方式或函数Bean方式)及接口测试的全流程。最终实现用户通过自然语言查询数据库的功能,展示了MCP在简化AI集成、提升系统易用性方面的价值。未来,“对话即服务”有望成为主流开发范式。
9075 7
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
2322 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践

热门文章

最新文章

下一篇
开通oss服务