eureka 2.0 - Service URL

134 views
Skip to first unread message

sanjayv...@gmail.com

unread,
Mar 25, 2015, 10:31:34 PM3/25/15
to eureka_...@googlegroups.com
Hi,

Great to see Eureka 2.0 initial API usage documentation. Using the Eureka 2.0 Client API, I want an easy way to get the URL of a target service to use for my HTTP call using the InterestClient. As an example:

Interest<InstanceInfo> myInterest = Interests.forApplications("MyWebService");

// I'd like to do the following but not sure on the right way to do it
InstanceInfo info = interestClient.getInstanceInfo(); // No such method though

httpClient.execute(info.getHostName() + info.getPort() + "/someResource");

Whats the best way to get a URL from the registry for a client to communicate with the server. It would be painful to have to subscribe and then maintain the list of server instances somewhere else.

I hope my question makes sense?

Thanks,
Sanjay

dl...@netflix.com

unread,
Mar 26, 2015, 2:02:00 AM3/26/15
to eureka_...@googlegroups.com, sanjayv...@gmail.com
Hi Sanjay,

Will your webService be primarily composed of a single instance or a cluster of instances? It seems like for your usecase, you are looking to just get hold of a single instance (regardless of whether they are in a cluster), and as soon as a single instance is available, your want to be able to use this instance to make a webservice call.

The current eureka2 API exposes are pretty low level and assumes a generic case of multi instance clusters that can be load balanced around for making web service calls. You can achieve your goal (if it is what I assumed above) by directly using eureka2 in the following ways:

--- non-blocking ---
        interestClient.forInterest(forApplications("myApp"))
                .filter(new Func1<ChangeNotification<InstanceInfo>, Boolean>() {
                    @Override
                    public Boolean call(ChangeNotification<InstanceInfo> notification) {
                        // filter out all non-data and delete notifications
                        return notification.isDataNotification() && notification.getKind() != ChangeNotification.Kind.Delete;
                    }
                })
                .take(1)
                .map(new Func1<ChangeNotification<InstanceInfo>, Object>() {
                    @Override
                    public Object call(ChangeNotification<InstanceInfo> notification) {
                        InstanceInfo info = notification.getData();
                        NetworkAddress address = ServiceSelector.selectBy().publicIp(true).returnNetworkAddress(info);
                        // make call on the address only when the instanceInfo is returned
                    }
                });

--- blocking ---
        InstanceInfo info = interestClient.forInterest(forApplications("myApp"))
                .filter(new Func1<ChangeNotification<InstanceInfo>, Boolean>() {
                    @Override
                    public Boolean call(ChangeNotification<InstanceInfo> notification) {
                        // filter out all non-data and delete notifications
                        return notification.isDataNotification() && notification.getKind() != ChangeNotification.Kind.Delete;
                    }
                })
                .map(new Func1<ChangeNotification<InstanceInfo>, InstanceInfo>() {
                    @Override
                    public InstanceInfo call(ChangeNotification<InstanceInfo> notification) {
                        return notification.getData();
                    }
                })
                .take(1)
                .toBlocking()
                .firstOrDefault(null);

        NetworkAddress address = ServiceSelector.selectBy().publicIp(true).returnNetworkAddress(info);
        // make call on the address

you can also work with a list of server instances:

        InstanceInfo info = interestClient.forInterest(forApplications("myApp"))
                .compose(ChangeNotificationFunctions.<InstanceInfo>buffers())
                .compose(ChangeNotificationFunctions.<InstanceInfo>snapshots())
                .take(1)
                .map(new Func1<LinkedHashSet<InstanceInfo>, Object>() {
                    @Override
                    public Object call(LinkedHashSet<InstanceInfo> instanceInfos) {
                        // work with a latest snapshot list of servers for the app
                    }
                });

We also want to provide some higher level APIs within eureka to make certain use cases easier, and any feedback you can provide on that would be very appreciated.

I would also encourage you to combine the use of eureka with Ocelli loadbalancer (see https://github.com/Netflix/ocelli). The integration with the rc.1 release of eureka2 is not quite ready yet (I can let you know when it is), but the intended goal is that you should be able to feed an eureka2 interest stream into the ocelli loadbalancer, and from there you can just query the loadbalancer to return the next "best available" server to make queries to. The LB will provide a lot of additional value such as loadbalancing, failure detection etc.

Thanks,
David

sanjayv...@gmail.com

unread,
Mar 26, 2015, 7:06:05 AM3/26/15
to eureka_...@googlegroups.com, sanjayv...@gmail.com
Hi David,

I think you have my use case. I am hoping to use Eureka for client side load balancing on a set of server instances. I will try out your code snippet, thanks.

I am hoping that the strategy for load balancing can be configured with the ability to mark a server instance as faulty and not used (potentially for a period of time), if for example I receive a network error on it. If a server is not available etc, don't want to have to call it on other requests.

I am using jersey and get notified of say a Socket Exception etc and can notify the service discovery mechanism on a server in error.

With Ocelli, where does Ribbon fit into all this?

As you mentioned, I am hoping to use the eureka 2 client API to simply provide me a 'server' I can call. If I can set up Ocelli with an interest stream and then obtain back a server from Ocelli that would be great. It would also be good to be able to tell Ocelli to temporarily or permanently ignore a server based of a degradation policy.

I apologize if I am jumping ahead of the horse here, but I am excited to see where this is going.

Thanks,
Sanjay

Nitesh Kant

unread,
Mar 26, 2015, 12:05:58 PM3/26/15
to eureka_...@googlegroups.com, sanjayv...@gmail.com
Hi Sanjay,

Ocelli does provide what you are looking for from failure detection to pluggable LB strategies. You can play with it and raise issues in the repo for questions/bugs. 

I would like you to understand that Ocelli is a very early stage library and we are not committing to any API/functionality as of today. It will be changing rapidly in the days to come. So, if you are looking for a stable library, I would recommend waiting for a while. 

>> With Ocelli, where does Ribbon fit into all this

You can think of ocelli as the new version of ribbon load balancing to make it reactive & flexible for usecases other than HTTP. We pulled out ocelli into a separate repo as we thought it was impeding adoption of a generic load balancing library which can be used by any client for any protocol. 
--
You received this message because you are subscribed to the Google Groups "eureka_netflix" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eureka_netfli...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

sanjayv...@gmail.com

unread,
Mar 27, 2015, 11:52:31 AM3/27/15
to eureka_...@googlegroups.com, sanjayv...@gmail.com
Hi Nitesh,

Thanks for the clarification on Ribbon versus Ocelli. I understand that the API is volatile at this point. In my use case, I will be obtaining a Host from the load balancer, invoking a request and if it were to fail, would like to notify the load balancer and underlying strategy of a failure with the mentioned host so the underlying strategy would be able to determine when and if the host gets used next.
For example:

List<Instance<Host>> instances = membershipSource
.forInterest(interest)
.take(1)
.toList().toBlocking()
.toFuture()
.get(1, TimeUnit.SECONDS);

try {
String url = ...//computed from host
jerseyClient.execute(url);
}
catch (ProcessingException e) {
memershipSource.noteFailure(url); // Or tell some Ocelli class
}

If my understanding is right, it looks like Ocelli expects a Callback and handles exception and strategy. Would there be a way to do this without having to call Ocelli via a Callback where the client is provided?

Again if this premature, never mind and if this is the wrong forum for this question, I apologize.

Nitesh Kant

unread,
Mar 27, 2015, 4:52:38 PM3/27/15
to eureka_...@googlegroups.com, Sanjay Acharya
>> Again if this premature, never mind and if this is the wrong forum for this question, I apologize

Yeah I think it is purely an ocelli question and you will get better answers on the ocelli repo. Feel free to open an issue on ocelli and ask the question.

Reply all
Reply to author
Forward
0 new messages