Eureka解析

一、简介

    Eureka是Netflix提供的一个用于作为注册中心的组件。提供服务注册、服务发现等功能。

二、结构图

    Eureka可以做集群部署,提供高可用性。如下是它的结构图。图片来源:https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance

图中包含两个组件:Eureka Client、Eureka Server。服务提供者跟服务调用方都是作为Eureka Client向Eureka Server注册。

  • Application Service向Eureka Server进行注册
  • Applocation Client向Eureka Server获取服务注册信息
  • Applocation Client调用 Application Service

三、功能介绍

1、服务注册

    服务提供者在启动的时候,会将自己服务信息,包括IP、port等提交给Eureka Server进行注册工作。在eureka-client.1.9.2.jar里面,有一个com.netflix.discovery.DiscoveryClient类,其中有一个register(),从代码中可以看出通过http向Eureka Server进行注册操作。


在eureka-core.1.9.2.jar里面,在com.netflix.eureka.resources.ApplicationResource里面提供了addInstance供客户端进行注册调用。com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl里有提供register,在服务注册成功之后会及时的同步到别的server节点。

public void register(InstanceInfo info, boolean isReplication) {
    int leaseDuration = 90;
    if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
        leaseDuration = info.getLeaseInfo().getDurationInSecs();
    }

    super.register(info, leaseDuration, isReplication);
    this.replicateToPeers(PeerAwareInstanceRegistryImpl.Action.Register, info.getAppName(), info.getId(), info, (InstanceStatus)null, isReplication);
}

2、服务发现

    服务消费者在启动的时候,会根据已经配置的Eureka Server信息,去拉取已经注册的服务信息。在eureka-client.1.9.2.jar里面,有一个com.netflix.discovery.DiscoveryClient类,在其初始化的过程中调用了initScheduledTasks(),用来向服务端拉取服务信息

@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, Provider<BackupRegistry> backupRegistryProvider) {
    ...省略...
    logger.info("Initializing Eureka in region {}", this.clientConfig.getRegion());
    if (!config.shouldRegisterWithEureka() && !config.shouldFetchRegistry()) {
        ...省略...
    } else {
        ...省略...
        this.initScheduledTasks();
        ...省略...
    }

在这里通过定时器拉取服务注册信息。

private void initScheduledTasks() {
    ...省略...
    if (this.clientConfig.shouldFetchRegistry()) {
        renewalIntervalInSecs = this.clientConfig.getRegistryFetchIntervalSeconds();
        expBackOffBound = this.clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
        this.scheduler.schedule(new TimedSupervisorTask("cacheRefresh", this.scheduler, this.cacheRefreshExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.CacheRefreshThread()), (long)renewalIntervalInSecs, TimeUnit.SECONDS);
    }
    ...省略...
}

runnable里面会通过HTTP进行服务拉取。

private void getAndStoreFullRegistry() throws Throwable {
    long currentUpdateGeneration = this.fetchRegistryGeneration.get();
    logger.info("Getting all instance registry info from the eureka server");
    Applications apps = null;
    EurekaHttpResponse<Applications> httpResponse = this.clientConfig.getRegistryRefreshSingleVipAddress() == null ? this.eurekaTransport.queryClient.getApplications((String[])this.remoteRegionsRef.get()) : this.eurekaTransport.queryClient.getVip(this.clientConfig.getRegistryRefreshSingleVipAddress(), (String[])this.remoteRegionsRef.get());
    if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
        apps = (Applications)httpResponse.getEntity();
    }

    logger.info("The response status is {}", httpResponse.getStatusCode());
    if (apps == null) {
        logger.error("The application is null for some reason. Not storing this information");
    } else if (this.fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1L)) {
        this.localRegionApps.set(this.filterAndShuffle(apps));
        logger.debug("Got full registry with apps hashcode {}", apps.getAppsHashCode());
    } else {
        logger.warn("Not updating applications as another thread is updating it already");
    }

}

3、服务续约

    服务提供者在启动的时候,会将自己服务信息,包括IP、port等提交给Eureka Server进行注册工作。在eureka-client.1.9.2.jar里面,有一个com.netflix.discovery.DiscoveryClient类,其中有一个renew(),通过HTTP向Eureka Server进行续约。

boolean renew() {
    try {
        EurekaHttpResponse<InstanceInfo> httpResponse = this.eurekaTransport.registrationClient.sendHeartBeat(this.instanceInfo.getAppName(), this.instanceInfo.getId(), this.instanceInfo, (InstanceStatus)null);
        logger.debug("DiscoveryClient_{} - Heartbeat status: {}", this.appPathIdentifier, httpResponse.getStatusCode());
        if (httpResponse.getStatusCode() == 404) {
            this.REREGISTER_COUNTER.increment();
            logger.info("DiscoveryClient_{} - Re-registering apps/{}", this.appPathIdentifier, this.instanceInfo.getAppName());
            long timestamp = this.instanceInfo.setIsDirtyWithTime();
            boolean success = this.register();
            if (success) {
                this.instanceInfo.unsetIsDirty(timestamp);
            }

            return success;
        } else {
            return httpResponse.getStatusCode() == 200;
        }
    } catch (Throwable var5) {
        logger.error("DiscoveryClient_{} - was unable to send heartbeat!", this.appPathIdentifier, var5);
        return false;
    }
}
在eureka-core.1.9.2.jar里面,在com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl里有提供renew

public boolean renew(String appName, String id, boolean isReplication) {
    if (super.renew(appName, id, isReplication)) {
        this.replicateToPeers(PeerAwareInstanceRegistryImpl.Action.Heartbeat, appName, id, (InstanceInfo)null, (InstanceStatus)null, isReplication);
        return true;
    } else {
        return false;
    }
}

4、时间参数

Eureka有2个时间参数。30、90。每30s发送一次续约请求,如果90s没有收到续约请求,则会将某一个服务实例剔除。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值