为了熟悉 Spring Cloud 的 Eureka 客户端/服务器机制,我尝试将客户端连接到 Eureka 服务器,并每 5 分钟打开/关闭连接,以查看 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 的回答,我的解决方案是添加一个自定义 @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();
}
}