微服务发现组件Eureka Server源码解读篇

本文深入解析Eureka Server的工作原理,包括instanceInfo服务实例信息、Lease租约概念、LeaseInfo租约详情以及LeaseManager接口。重点分析核心类AbstractInstanceRegistry,探讨其注册、心跳、剔除和服务下线的实现。同时指出Eureka Server自身也是一个Eureka Client,并介绍了服务剔除的定时任务EvictionTask。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇说到Eureka客户端,这篇分析服务器端是如何与客户端交互及实现了哪些功能

这里解释一些Eureka的专有名词
instanceInfo: 服务实例信息,  instanceId(唯一),app, appGroupName, ipAddr, port, leaseInfo等
Lease:租约,客户端向服务器端注册相当于签下了一纸租约,存在租期的概念,到期了要是没动静就默认不租了,把实例剔除。非常形象生动
LeaseInfo:使用了内联构造器的设计模式,来标识实例的租约信息,例如服务器端:注册时间、最后一次续约时间、被剔除时间、标记为UP的时间,客户端:续约间隔时间、租约的有效时长
LeaseManager:望文生义,这个接口负责管理实例,那么要知道如何管理服务注册、服务下线、服务续约和服务剔除,查看这个接口的实现类就能明白。

所以,查看LeaseManager的类图,看到类的继承关系,大致就明白,AbstractInstanceRegistry就是LeaseManager的基本实现类,它还同时实现了LookupService

LookupService接口的实现类还有DiscoveryClient, 主要的作用是发现活跃的服务实例,那么可否认为Eureka Server也是一个Eureka Client呢,因为和DiscoveryClient功能实现很像。事实上是可以的,Eureka Server同时也是一个Eureka Client, 这就是在配置时要注意的,如果不想注册Eureka Server为Client时,registerWithEureka属性设置为true的原因。

registerWithEureka: false #先不向Eureka Server注册自己的信息

那么基本框架大致讲到这里,接下来就详细讲解AbstractInstanceRegistry这个Eureka Server的核心类,其中registry就是注册表,结构如下

ConcurrentHashMap<String/*app name*/, Map<String/*InstanceId*/, Lease<InstanceInfo>>> registry = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();

服务注册 AbstractInstanceRegistry#register

public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
    try {
        // 获取读锁
        read.lock();
        // 根据appName对服务实例集群进行分类
        Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
        REGISTER.increment(isReplication);
        if (gMap == null) {
            final ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = new ConcurrentHashMap<String, Lease<InstanceInfo>>();
            // 如果存在键值,直接返回已存在的值,否则添加该键值对
            gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap);
            if (gMap == null) {
                gMap = gNewMap;
            }
        }
                // 根据instanceId获取实例的租约
        Lease<InstanceInfo> existingLease = gMap.get(registrant.getId());
        // Retain the last dirty timestamp without overwriting it, if there is already a lease
        if (existingLease != null && (existingLease.getHolder() != null)) {
            Long existingLastDirtyTimestamp = existingLease.getHolder().getLastDirtyTimestamp();
            Long registrationLastDirtyTimestamp = registrant.getLastDirtyTimestamp();
            logger.debug("Existing lease found (existing={}, provided={}", existingLastDirtyTimestamp, registrationLastDirtyTimestamp);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值