Search code examples
javascriptnode.jsnetflix-eurekaeureka-js-client

Unable to retrieve instance from Eureka server using JS client


I'm having a problem trying to get a service URL discover by eureka.

I'm using eureka-js-client to connect to Eureka and for testing purposes I've created two microservices, I've called it: ms1 and ms2.

What I've tried is:

  • Start Eureka server to allow services register into it
  • Start ms1 and register into Eureka
  • Start ms2, register into Eureka and get ms1 URL.

To accomplish this I've launched eureka server as a Spring Boot app using @EnableEurekaServer. This part works fine, I can access http://localhost:8761/ and see the dashboard.

Then, in my microservices I've this configuration

this._client = new Eureka({
                instance: {
                    app: 'ms1',
                    instanceId: 'ms1',
                    hostName: 'localhost',
                    ipAddr: '127.0.0.1',
                    statusPageUrl: `http://localhost:${port ? port : this._port}`,
                    healthCheckUrl: `http://localhost:${port? port : this._port}/health`,
                    port: {
                        '$': port? port: this._port,
                        '@enabled': true,
                    },
                    vipAddress: 'myvip',
                    dataCenterInfo: {
                        '@class': 'com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo',
                        name: 'MyOwn',
                    },
                },
                eureka: {
                    host: 'localhost',
                    port: 8761,
                    servicePath: '/eureka/apps/'
                },
            })

And the same for ms2 changing the name.

When I run the project it output registered with eureka: ms1/ms1 and services seems to be registered in eureka correctly: enter image description here

But now the problem is trying to get the URL of one of the two services. From either of the two services, if I try to get the Eureka instances I always get an empty list.

I have this code:

let instances: any = this.getClient().getInstancesByAppId(microserviceName);
let instance = null;
let url = ''
if (instances != null && instances.length > 0) {
    instance = instances[0];
    let protocol = instance.securePort["@enabled"] == "true" ? "https" : "http";
    url = `${protocol}//${instance.ipAddr}:${instance.port.$}/`
}

Where in "microserviceName" variable I've tried:

  • "ms1"
  • "MS1"
  • "ms1/ms1"

But the response is always an empty array with this output:

Unable to retrieve instances for appId: ms1

So, what's the problem? Have I missed something? I think the flow is correct:

  1. Start Eureka server.
  2. Register services into server.
  3. Look for instances in the server.

Thanks in advance.


Solution

  • Finally I solved my own issue. All was working good, the ms2 was able to find ms1 using the code I posted, so the problem was:

    My ms2 file was like this:

    EurekaService.getClient().start()
    EurekaService.getUrl('ms1')
    EurekaService.getClient()?.stop()
    

    And it seems like EurekaService.getClient().start() does not block until it ends (or is available or whatever), so the client is not up and can't get the instance ms1.

    Note that the method getUrl() has the code provided in the OP:

    let instances: any = this.getClient().getInstancesByAppId(microserviceName);
    let instance = null;
    ...
    

    So I've changed the code like this:

    start()
    async function start(){
        EurekaService.getClient().start()
        await new Promise(f => setTimeout(f, 1000));
        const url = EurekaService.getUrl('ms1')
        console.log("url = ",url)
        EurekaService.getClient()?.stop()
    }
    

    And works perfectly, the output log is:

    registered with eureka:  ms2/ms2
    url =  http//127.0.0.1:8002/
    de-registered with eureka: ms2/ms2
    

    So, start method is not async so I can't use await or .then(), I have to set a timeout and wait to complete.

    I don't know if there is a better way to do this or by the nature of the architecture can't be controlled when is available.

    By the way, for me, 1 second timeout is enough.