To familiarize myself with Spring Cloud's Eureka client/server mechanism, I try to connect a client to the Eureka server and toggle the connection on/off every 5 minutes to see how the Eureka server handles this.
I have two Eureka clients.
- The first on is giving me information about the registered applications with this code:
- @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);
- }
- The second Eureka Client register/deregister itself every 5 minutes:
- 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();
- }
- }
- The log output of the second Eureka client looks as follows:
- 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
When starting both Eureka clients for the first time, this works well. The second client is shown by the first client AND the second client is visible in die Eureka server console. When the second client disconnects itself from the Eureka server, it is no longer listed there and the first client is also not showing it anymore.
- Unfortunately, when the second client reconnects to the Eureka server, the Eureka server console is just showing a big red highlighted "DOWN (1)" and the first client is not showing the second client anymore. What am I missing here?
- Solution:
- Based on Dave Sayer's answer https://stackoverflow.com/a/29280258/1089459 my solution was to add a custom @Configuration that has the EurekaDiscoveryClientConfiguration autowired and starts a thread for toggling the registration. Note that this is for test purposes only, so it may be a quite ugly solution ;-)
- @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();
- }
- }
answer 1>> 解决方法
- Your call to DiscoveryManager.getInstance().initComponent() does not set the status (and the default is DOWN). In Spring Cloud we handle it in a special EurekaDiscoveryClientConfiguration.start() lifecycle. You could inject that and re-use it like this:
- @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();
- }
- (which is code taken from here: ).
来源: http://www.itkeyword.com/doc/8836415955233883x335/spring-cloud-eureka-client-registration-deregistration-cycl