EvilJinious1
EvilJinious1

Reputation: 2863

Spring cloud eureka client to multiple eureka servers

I am able to get the eureka server to operate in a peer to peer mode. But one thing I am curious about is how do I get a service discovery client to register to multiple eureka servers.

My use case is this:
Say I have a service registering to one of the eureka servers (e.g. server A) and that registration is replicated to its peer. The service is actually pointing at server A. If server A goes down, and the client expects to renew with server A, how do the renewal work if server A is no longer present. Do I need to register with both and if not then how does the renewal happen if the client cannot communicate with server A. Does it have some knowledge of server B (from its initial and/or subsequent comms with A) and fail over to do its registration renewal there? That is not clear in any of the docs and I need to verify

So based on the answer, I added the following to my application.yml

eureka:
  # these are settings for the client that gets services
  client:
    # enable these two settings if you want discovery to work
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://localhost:8762/eureka/, http://localhost:8761/eureka/

It only registers to the first in the comma separated list. If I switch them around the registration flips between eureka servers.

I can see that it does separate these based on comma but my guess is that Eureka does not use this underneath (from EurekaClientConfigBean.java)

    @Override
    public List<String> getEurekaServerServiceUrls(String myZone) {
        String serviceUrls = this.serviceUrl.get(myZone);
        if (serviceUrls == null || serviceUrls.isEmpty()) {
            serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
        }
        if (serviceUrls != null) {
            return Arrays.asList(serviceUrls.split(","));
        }

        return new ArrayList<>();
    }

Upvotes: 9

Views: 7956

Answers (5)

mostafa cs
mostafa cs

Reputation: 738

If you want to a workaround to register on multiple eureka servers. please review my answer on similar question: https://stackoverflow.com/a/60714917/7982168

Upvotes: 0

Lalchand Mali
Lalchand Mali

Reputation: 221

Please add below property in application.property or application.yml file

eureka.client.service-url.defaultZone = http://localhost:8761/eureka,http://localhost:8762/eureka

Services will be registered with both eureka server.If one eureka server is down then request will be served from other eureka server.

Upvotes: 0

DJPillowhead
DJPillowhead

Reputation: 41

Yes, as per the documentation, the flow is:

  1. client registers to the first available eureka server
  2. registrant information is replicated between eureka server nodes.

So multiple registration is not only not needed but should be avioded.

Upvotes: 2

EvilJinious1
EvilJinious1

Reputation: 2863

I just reviewed the source code for Eureka 1.1.147. It works differently that i expected but at least I know now.

You can put multiple service urls in the set

serviceUrl:
      defaultZone: http://localhost:8762/eureka/, http://localhost:8761/eureka/

But the register action only uses the first one to register. There remaining are used only if attempting to contact the first fails.

from (DiscoveryClient.java)

   /**
     * Register with the eureka service by making the appropriate REST call.
     */
    void register() {
        logger.info(PREFIX + appPathIdentifier + ": registering service...");
        ClientResponse response = null;
        try {
            response = makeRemoteCall(Action.Register);
            isRegisteredWithDiscovery = true;
            logger.info(PREFIX + appPathIdentifier + " - registration status: "
                    + (response != null ? response.getStatus() : "not sent"));
        } catch (Throwable e) {
            logger.error(PREFIX + appPathIdentifier + " - registration failed"
                    + e.getMessage(), e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

which calls

private ClientResponse makeRemoteCall(Action action) throws Throwable {
    return makeRemoteCall(action, 0);
}

It only calls the backup when an exception is thrown in the above makeRemoteCall(action, 0) call

   } catch (Throwable t) {
            closeResponse(response);
            String msg = "Can't get a response from " + serviceUrl + urlPath;
            if (eurekaServiceUrls.get().size() > (++serviceUrlIndex)) {
                logger.warn(msg, t);
                logger.warn("Trying backup: " + eurekaServiceUrls.get().get(serviceUrlIndex));
                SERVER_RETRY_COUNTER.increment();
                return makeRemoteCall(action, serviceUrlIndex);
            } else {
                ALL_SERVER_FAILURE_COUNT.increment();
                logger.error(
                        msg
                                + "\nCan't contact any eureka nodes - possibly a security group issue?",
                        t);
                throw t;
            }

So you can't really register to two eureka servers simultaneously from this code. Unless I missed something.

Upvotes: 11

Robert Greathouse
Robert Greathouse

Reputation: 1034

Your client application should be provided a list of Eureka URLs. The URLs are comma separated.

Upvotes: 1

Related Questions