eru
状态说明
STARTING : 表示服务正在启动中
DOWN: 表示服务已经宕机,无法继续提供服务
UP : 服务正常运行
OUT_OF_SERVICE : 不再提供服务,其他的Eureka Client将调用不到该服务,一般有人为的调用接口设置的,如:强制下线。
UNKNOWN: 未知状态
状态变更
容器启动
在容器刚刚启动,实例化instance信息的时候,默认状态为STARTING
@Bean
@conditionalOnMissingBean(value = APPlicationInfoManager.class, search = SearchStrategy.CURRENT)
@org.Springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public ApplicationInfoManager eurekaApplicationInfoManager(EurekainstanceConfig config) {
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
return new ApplicationInfoManager(config, instanceInfo);
}
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public ApplicationInfoManager eurekaApplicationInfoManager(EurekaInstanceConfig config) {
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
return new ApplicationInfoManager(config, instanceInfo);
}
初始化ApplicationInfoManager的时候,会设置一个最初的Instance信息,这个时候的instance信息的状态为STARTING
public InstanceInfo create(EurekaInstanceConfig config) {
leaseInfo.builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder()
.setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds())
.setDurationInSecs(config.getLeaseExpirationDurationInSeconds());
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();
// ..... 省略N多代码
// config.isInstanceEnabledOnit() 默认为false
if (!config.isInstanceEnabledOnit()) {
// 设置实例的状态为STARTING
InstanceInfo.InstanceStatus initialStatus = InstanceInfo.InstanceStatus.STARTING;
if (log.isInfoEnabled()) {
log.info("Setting initial instance status as: " + initialStatus);
}
builder.setStatus(initialStatus);
}
// ..... 省略N多代码
InstanceInfo instanceInfo = builder.build();
instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
return instanceInfo;
}
InstanceInfo create(EurekaInstanceConfig config) {
LeaseInfo.Builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder()
.setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds())
.setDurationInSecs(config.getLeaseExpirationDurationInSeconds());
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();
// ..... 省略N多代码
// config.isInstanceEnabledOnit() 默认为false
if (!config.isInstanceEnabledOnit()) {
// 设置实例的状态为STARTING
InstanceInfo.InstanceStatus initialStatus = InstanceInfo.InstanceStatus.STARTING;
if (log.isInfoEnabled()) {
log.info("Setting initial instance status as: " + initialStatus);
}
builder.setStatus(initialStatus);
}
// ..... 省略N多代码
InstanceInfo instanceInfo = builder.build();
instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
return instanceInfo;
}
上面的代码是做了一些初始化的信息,设置Instance的状态为STARTING,接下来,在自动注册类初始化的时候,
会设置Instance的状态为UP,同时触发监听器,让Eureka Client发起注册。
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
流程图如下:
1528437997(1).jpg
关于容器启动时注册的具体细节,可以细看https://blog.csdn.net/u012394095/article/details/80693713中自动注册那一小结
健康检查器
在Eureka Client端,有一个40秒执行一次的定时任务,会定时的去扫描自身的信息,查看自身信息是否发生改变,
其中就有一个对状态的检测,这个时候,如果设置了健康检查器,那么会以健康检查的结果为准,判断当前实例的
状态
// DiscoverClient.java
void refreshInstanceInfo() {
// 1. 判断数据中心的数据是否发生改变,
applicationInfoManager.refreshDataCenterInfoIfrequired();
// 2.判断配置是否发生改变
applicationInfoManager.refreshLeaseInfoIfRequired();
InstanceStatus status;
try {
// 通过健康检查器,获取应用的最新状态
status = getHealthCheckhandler().getStatus(instanceInfo.getStatus());
} catch (Exception e) {
logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", e);
status = InstanceStatus.DOWN;
}
if (null != status) {
// 设置状态
applicationInfoManager.setInstanceStatus(status);
}
}
// DiscoverClient.java
void refreshInstanceInfo() {
// 1. 判断数据中心的数据是否发生改变,
applicationInfoManager.refreshDataCenterInfoIfRequired();
// 2.判断配置是否发生改变
applicationInfoManager.refreshLeaseInfoIfRequired();
InstanceStatus status;
try {
// 通过健康检查器,获取应用的最新状态
status = getHealthCheckHandler().getStatus(instanceInfo.getStatus());
} catch (Exception e) {
logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", e);
status = InstanceStatus.DOWN;
}
if (null != status) {
// 设置状态
applicationInfoManager.setInstanceStatus(status);
}
}
健康检查器,获取状态。
@Override
public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus) {
// 判断instance的状态。
if (null == callback || InstanceInfo.InstanceStatus.STARTING == currentStatus
|| InstanceInfo.InstanceStatus.OUT_OF_SERVICE == currentStatus) { // Do not go to healthcheck handler if the status is starting or OOS.
return currentStatus;
}
return callback.isHealthy() ? InstanceInfo.InstanceStatus.UP : InstanceInfo.InstanceStatus.DOWN;
}
@Override
public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus) {
// 判断instance的状态。
if (null == callback || InstanceInfo.InstanceStatus.STARTING == currentStatus
|| InstanceInfo.InstanceStatus.OUT_OF_SERVICE == currentStatus) { // Do not go to healthcheck handler if the status is starting or OOS.
return currentStatus;
}
return callback.isHealthy() ? InstanceInfo.InstanceStatus.UP : InstanceInfo.InstanceStatus.DOWN;
}
代码如上,如果callback对象不为空的话,那么会调用callback的isHealthy()方法判断实例的状态。
同时会将获取到的状态调用 applicationInfoManager.setInstanceStatus(status) , 只有当传入的
状态和他本身的状态不一致时,才会更新, 如果更新了状态,那么同时也会想服务器注册最新的信息
具体可以看 :https://blog.csdn.net/u012394095/article/details/80966441
强制下线
下篇讲解
容器销毁
在使用kill pid 这种方式去终止进程的时候,spring容器会销毁,在销毁的时候会触发一些shutDown这种方法。
EurekaAutoServiceRegistration是一个实现了SmartLifecycle的接口类,在spring容器销毁的时候,会调用其
stop方法。
@Override
public void stop() {
this.serviceRegistry.deregister(this.registration);
this.running.set(false);
}
@Override
public void stop() {
this.serviceRegistry.deregister(this.registration);
this.running.set(false);
}
调用了deregister方法,
@Override
public void deregister(EurekaRegistration reg) {
if (reg.getApplicationInfoManager().getInfo() != null) {
if (log.isInfoEnabled()) {
log.info("Unregistering application " + reg.getInstanceConfig().getAppname()
+ " with eureka with status DOWN");
}
// 设置实例的状态为DOWN
reg.getApplicationInfoManager().setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);
//触发DiscoverClient的shutdown方法
reg.getEurekaClient().shutdown();
}
}
@Override
public void deregister(EurekaRegistration reg) {
if (reg.getApplicationInfoManager().getInfo() != null) {
if (log.isInfoEnabled()) {
log.info("Unregistering application " + reg.getInstanceConfig().getAppname()
+ " with eureka with status DOWN");
}
// 设置实例的状态为DOWN
reg.getApplicationInfoManager().setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);
//触发DiscoverClient的shutdown方法
reg.getEurekaClient().shutdown();
}
}
reg.getApplicationInfoManager().setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);
这行代码,设置了实例的状态为DOWN,这个时候会触发状态监听器,将实例的最新状态重新注册到Eureka上面去
,这个时候在Eureka上面的状态,该类的状态就是DOWN,通过日志可以很详细的看出来
Eureka Client
2018-06-08 15:14:46.944 [Thread-12] INFO o.s.c.n.e.serviceregistry.EurekaServiceRegistry - Unregistering application gs-job-admin with eureka with status DOWN
2018-06-08 15:14:46.944 [Thread-12] WARN com.netflix.discovery.DiscoveryClient - Saw local status change event StatusChangeEvent [timestamp=1528442086944, current=DOWN, previous=UP]
2018-06-08 15:14:46.945 [DiscoveryClient-InstanceInfoReplicator-0] INFO com.netflix.discovery.DiscoveryClient - DiscoveryClient_GS-JOB-ADMIN/10.28.144.127:8200: registering service...
2018-06-08 15:14:46.946 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - Shutting down DiscoveryClient ...
2018-06-08 15:14:46.948 [DiscoveryClient-InstanceInfoReplicator-0] INFO com.netflix.discovery.DiscoveryClient - DiscoveryClient_GS-JOB-ADMIN/10.28.144.127:8200 - registration status: 204
2018-06-08 15:14:46.948 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - Unregistering ...
2018-06-08 15:14:46.953 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - DiscoveryClient_GS-JOB-ADMIN/10.28.144.127:8200 - deregister status: 200
2018-06-08 15:14:46.955 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - Completed shut down of DiscoveryClient
2018-06-08 15:14:46.944 [Thread-12] INFO o.s.c.n.e.serviceregistry.EurekaServiceRegistry - Unregistering application gs-job-admin with eureka with status DOWN
2018-06-08 15:14:46.944 [Thread-12] WARN com.netflix.discovery.DiscoveryClient - Saw local status change event StatusChangeEvent [timestamp=1528442086944, current=DOWN, previous=UP]
2018-06-08 15:14:46.945 [DiscoveryClient-InstanceInfoReplicator-0] INFO com.netflix.discovery.DiscoveryClient - DiscoveryClient_GS-JOB-ADMIN/10.28.144.127:8200: registering service...
2018-06-08 15:14:46.946 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - Shutting down DiscoveryClient ...
2018-06-08 15:14:46.948 [DiscoveryClient-InstanceInfoReplicator-0] INFO com.netflix.discovery.DiscoveryClient - DiscoveryClient_GS-JOB-ADMIN/10.28.144.127:8200 - registration status: 204
2018-06-08 15:14:46.948 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - Unregistering ...
2018-06-08 15:14:46.953 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - DiscoveryClient_GS-JOB-ADMIN/10.28.144.127:8200 - deregister status: 200
2018-06-08 15:14:46.955 [Thread-12] INFO com.netflix.discovery.DiscoveryClient - Completed shut down of DiscoveryClient
Eureka Server
2018-06-08 15:14:47.455 eureka-resitry-ms 10.29.184.48 [http-nio-8081-exec-3] INFO c.e.p.b.e.r.listener.InstanceStateChangeListener.listen:108 - instance registered GS-JOB-ADMIN 10.28.144.127:8200 true DOWN, {management.port=18200}
2018-06-08 15:14:47.456 eureka-resitry-ms 10.29.184.48 [http-nio-8081-exec-3] INFO c.netflix.eureka.registry.AbstractInstanceRegistry.register:267 - Registered instance GS-JOB-ADMIN/10.28.144.127:8200 with status DOWN (replication=true)
2018-06-08 15:14:47.457 eureka-resitry-ms 10.29.184.48 [http-nio-8081-exec-3] INFO c.netflix.eureka.registry.AbstractInstanceRegistry.internalCancel:331 - Cancelled instance GS-JOB-ADMIN/10.28.144.127:8200 (replication=true)
2018-06-08 15:14:47.455 eureka-resitry-ms 10.29.184.48 [http-nio-8081-exec-3] INFO c.e.p.b.e.r.listener.InstanceStateChangeListener.listen:108 - instance registered GS-JOB-ADMIN 10.28.144.127:8200 true DOWN, {management.port=18200}
2018-06-08 15:14:47.456 eureka-resitry-ms 10.29.184.48 [http-nio-8081-exec-3] INFO c.netflix.eureka.registry.AbstractInstanceRegistry.register:267 - Registered instance GS-JOB-ADMIN/10.28.144.127:8200 with status DOWN (replication=true)
2018-06-08 15:14:47.457 eureka-resitry-ms 10.29.184.48 [http-nio-8081-exec-3] INFO c.netflix.eureka.registry.AbstractInstanceRegistry.internalCancel:331 - Cancelled instance GS-JOB-ADMIN/10.28.144.127:8200 (replication=true)
状态变更为DOWN 之后, Eureka Client会继续执行unregister()方法,执行下线操作。
sharedCode源码交流群,欢迎喜欢阅读源码的朋友加群,添加下面的微信, 备注”加群“ 。
相关阅读
这里所说的缩放不是指浏览器大小的缩放,而是指浏览器网页内容的百分比缩放(按Ctrl和+号键或者-号键的缩放)。检测这种缩放有很种方法
<html> <head> <title>DeviceOrientationEvent</title> <meta charset="UTF-8" /> <script src="https://libs.baid
重点内容HTTP 400 - 请求无效 HTTP 401.1 - 未授权:登录失败 HTTP 401.2 - 未授权:服务器配置问题导致登录失败 HTTP 401.3 - AC
对服务器程序来说,究竟是有状态服务,还是无状态服务,其判断依旧是指两个来自相同发起者的请求在服务器端是否具备上下文关系。如果是
机器如何知道用户的匹配兴趣?其实,这其中是有着具体的匹配规则的,本文将对其进行了简要概述。接上篇文章《社交领域不会有终局,除非人