eureka 集群失败的原因_eureka集群中的疑问?

题主的问题描述太绕了,我们先把集群中的角色定义下:

Eureka架构

比较细节的架构图如下所示:

在配置多个EurekaServer的Service Provider,每次Service Provider启动的时候会选择一个Eureka Server,之后如果这个Eureka Server挂了,才会切换Eureka Server,在当前使用的Eureka Server挂掉之前,不会切换。

被Service Provider选择用来发送请求Eureka Server其实比其他Server多了一项工作,就是发客户端发来的请求,转发到集群中其他的Eureka Server。其实这个压力并没有太大,但是如果集群中实例个数比较多,或者心跳间隔比较短的情况下,的确有不小的压力。可以考虑每个服务配置的Eureka Server顺序不一样。

但是其实仔细想想,只是个请求转发,能有多大压力啊。。。。

最后,我们详细分析下服务注册与取消的源代码(可以直接参考下我的博客关于Eureka的系列分析张哈希的博客 - CSDN博客​blog.csdn.net

):

关于服务注册开启/关闭服务注册配置:eureka.client.register-with-eureka = true (默认)

什么时候注册?应用第一次启动时,初始化EurekaClient时,应用状态改变:从STARTING变为UP会触发这个Listener,调用instanceInfoReplicator.onDemandUpdate(); 可以推测出,实例状态改变时,也会通过注册接口更新实例状态信息

statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {

@Override

public String getId() {

return "statusChangeListener";

}

@Override

public void notify(StatusChangeEvent statusChangeEvent) {

if (InstanceStatus.DOWN == statusChangeEvent.getStatus() ||

InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) {

// log at warn level if DOWN was involved

logger.warn("Saw local status change event {}", statusChangeEvent);

} else {

logger.info("Saw local status change event {}", statusChangeEvent);

}

instanceInfoReplicator.onDemandUpdate();

}

};定时任务,如果InstanceInfo发生改变,也会通过注册接口更新信息

public void run() {

try {

discoveryClient.refreshInstanceInfo();

//如果实例信息发生改变,则需要调用register更新InstanceInfo

Long dirtyTimestamp = instanceInfo.isDirtyWithTime();

if (dirtyTimestamp != null) {

discoveryClient.register();

instanceInfo.unsetIsDirty(dirtyTimestamp);

}

} catch (Throwable t) {

logger.warn("There was a problem with the instance info replicator", t);

} finally {

Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);

scheduledPeriodicRef.set(next);

}

}在定时renew时,如果renew接口返回404(代表这个实例在EurekaServer上面找不到),可能是之前注册失败或者注册过期导致的。这时需要调用register重新注册

boolean renew() {

EurekaHttpResponse httpResponse;

try {

httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);

logger.debug("{} - Heartbeat status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());

//如果renew接口返回404(代表这个实例在EurekaServer上面找不到),可能是之前注册失败或者注册过期导致的

if (httpResponse.getStatusCode() == 404) {

REREGISTER_COUNTER.increment();

logger.info("{} - Re-registering apps/{}", PREFIX + appPathIdentifier, instanceInfo.getAppName());

long timestamp = instanceInfo.setIsDirtyWithTime();

boolean success = register();

if (success) {

instanceInfo.unsetIsDirty(timestamp);

}

return success;

}

return httpResponse.getStatusCode() == 200;

} catch (Throwable e) {

logger.error("{} - was unable to send heartbeat!", PREFIX + appPathIdentifier, e);

return false;

}

}

向Eureka发送注册请求EurekaServer发生了什么?

主要有两个存储,一个是之前提到过的registry,还有一个最近变化队列,后面我们会知道,这个最近变化队列里面就是客户端获取增量实例信息的内容:

# 整体注册信息缓存

private final ConcurrentHashMap>> registry = new ConcurrentHashMap>>();

# 最近变化队列

private ConcurrentLinkedQueue recentlyChangedQueue = new ConcurrentLinkedQueue();

EurekaServer收到实例注册主要分两步:调用父类方法注册

同步到其他EurekaServer实例

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);

//同步到其他EurekaServer实例

this.replica

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值