Spring Cloud:Eureka 客户端注册/注销周期
Posted
技术标签:
【中文标题】Spring Cloud:Eureka 客户端注册/注销周期【英文标题】:Spring Cloud: Eureka Client registration/deregistration cycle 【发布时间】:2015-05-30 12:55:21 【问题描述】:为了熟悉 Spring Cloud 的 Eureka 客户端/服务器机制,我尝试将客户端连接到 Eureka 服务器,并每 5 分钟打开/关闭连接,以查看 Eureka 服务器如何处理此问题。
我有两个 Eureka 客户端。
首先是使用此代码向我提供有关已注册应用程序的信息:
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping(value = "/services", produces = MediaType.APPLICATION_JSON)
public ResponseEntity<ResourceSupport> applications()
ResourceSupport resource = new ResourceSupport();
Set<String> regions = discoveryClient.getAllKnownRegions();
for (String region : regions)
Applications allApps = discoveryClient.getApplicationsForARegion(region);
List<Application> registeredApps = allApps.getRegisteredApplications();
Iterator<Application> it = registeredApps.iterator();
while (it.hasNext())
Application app = it.next();
List<InstanceInfo> instancesInfos = app.getInstances();
if (instancesInfos != null && !instancesInfos.isEmpty())
//only show one of the instances
InstanceInfo info = instancesInfos.get(0);
resource.add(new Link(info.getHomePageUrl(), "urls"));
return new ResponseEntity<ResourceSupport>(resource, HttpStatus.OK);
第二个 Eureka 客户端每 5 分钟注册/注销一次:
private static final long EUREKA_INTERVAL = 5 * 60000;
public static void main(String[] args)
ConfigurableApplicationContext context = SpringApplication.run(MyServiceApplication.class);
long currentTime = System.currentTimeMillis();
long lastToggleTime = System.currentTimeMillis();
boolean connected = true;
while (true)
if (currentTime - lastToggleTime > EUREKA_INTERVAL)
if (connected)
System.err.println("disconnect");
DiscoveryManager.getInstance().shutdownComponent();
connected = false;
lastToggleTime = System.currentTimeMillis();
else
System.err.println("connect");
DiscoveryManager.getInstance().initComponent(
DiscoveryManager.getInstance().getEurekaInstanceConfig(),
DiscoveryManager.getInstance().getEurekaClientConfig());
connected = true;
lastToggleTime = System.currentTimeMillis();
currentTime = System.currentTimeMillis();
第二个Eureka客户端的日志输出如下:
disconnect
2015-03-26 13:59:23.713 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : DiscoveryClient_MYAPPNAME/MYMEGAHOSTNAME - deregister status: 200
connect
2015-03-26 14:04:23.870 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Disable delta property : false
2015-03-26 14:04:23.870 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Single vip registry refresh property : null
2015-03-26 14:04:23.870 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Force full registry fetch : false
2015-03-26 14:04:23.870 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Application is null : false
2015-03-26 14:04:23.870 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Registered Applications size is zero : true
2015-03-26 14:04:23.870 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Application version is -1: true
2015-03-26 14:04:23.889 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
2015-03-26 14:04:23.892 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : The response status is 200
2015-03-26 14:04:23.894 INFO 3452 --- [ main] com.netflix.discovery.DiscoveryClient : Starting heartbeat executor: renew interval is: 30
2015-03-26 14:04:53.916 INFO 3452 --- [ool-11-thread-1] com.netflix.discovery.DiscoveryClient : DiscoveryClient_MYAPPNAME/MYMEGAHOSTNAME - Re-registering apps/MYAPPNAME
2015-03-26 14:04:53.916 INFO 3452 --- [ool-11-thread-1] com.netflix.discovery.DiscoveryClient : DiscoveryClient_MYAPPNAME/MYMEGAHOSTNAME: registering service...
2015-03-26 14:04:53.946 INFO 3452 --- [ool-11-thread-1] com.netflix.discovery.DiscoveryClient : DiscoveryClient_MYAPPNAME/MYMEGAHOSTNAME - registration status: 204
第一次启动两个 Eureka 客户端时,效果很好。第二个客户端由第一个客户端显示,第二个客户端在 Eureka 服务器控制台中可见。 当第二个客户端与 Eureka 服务器断开连接时,它不再列在那里,第一个客户端也不再显示它。
不幸的是,当第二个客户端重新连接到 Eureka 服务器时,Eureka 服务器控制台只显示一个大红色突出显示的“DOWN (1)”,而第一个客户端不再显示第二个客户端。我在这里错过了什么?
解决方案:
基于 Dave Sayer 的 answer,我的解决方案是添加一个自定义 @Configuration,它具有自动装配的 EurekaDiscoveryClientConfiguration 并启动一个用于切换注册的线程。请注意,这仅用于测试目的,因此它可能是一个非常丑陋的解决方案;-)
@Configuration
static public class MyDiscoveryClientConfigServiceAutoConfiguration
@Autowired
private EurekaDiscoveryClientConfiguration lifecycle;
@PostConstruct
public void init()
new Thread(new Runnable()
@Override
public void run()
long currentTime = System.currentTimeMillis();
long lastToggleTime = System.currentTimeMillis();
boolean connected = true;
while (true)
if (currentTime - lastToggleTime > EUREKA_INTERVAL)
if (connected)
System.err.println("disconnect");
lifecycle.stop();
DiscoveryManager.getInstance().getDiscoveryClient().shutdown();
connected = false;
lastToggleTime = System.currentTimeMillis();
else
System.err.println("connect");
DiscoveryManager.getInstance().initComponent(
DiscoveryManager.getInstance().getEurekaInstanceConfig(),
DiscoveryManager.getInstance().getEurekaClientConfig());
lifecycle.start();
connected = true;
lastToggleTime = System.currentTimeMillis();
currentTime = System.currentTimeMillis();
).start();
【问题讨论】:
【参考方案1】:您对DiscoveryManager.getInstance().initComponent()
的调用不会设置状态(默认为DOWN)。在 Spring Cloud 中,我们在一个特殊的 EurekaDiscoveryClientConfiguration.start()
生命周期中处理它。您可以像这样注入并重新使用它:
@Autowired
private EurekaDiscoveryClientConfiguration lifecycle;
@PostConstruct
public void init()
this.lifecycle.stop();
if (DiscoveryManager.getInstance().getDiscoveryClient() != null)
DiscoveryManager.getInstance().getDiscoveryClient().shutdown();
ApplicationInfoManager.getInstance().initComponent(this.instanceConfig);
DiscoveryManager.getInstance().initComponent(this.instanceConfig,
this.clientConfig);
this.lifecycle.start();
(取自这里的代码:https://github.com/spring-cloud/spring-cloud-netflix/blob/master/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java#L58)。
【讨论】:
试试这个,谢谢戴夫!以上是关于Spring Cloud:Eureka 客户端注册/注销周期的主要内容,如果未能解决你的问题,请参考以下文章