rhavyn / norbert

Norbert is a cluster manager and networking layer built on top of Zookeeper.
Apache License 2.0
390 stars 125 forks source link

Can we have a Java load balancing example? #3

Open barryku opened 14 years ago

barryku commented 14 years ago

I am trying to use this library for a demo how we can use Zookeeper for load balancing, and came across this library. It will be great if you can include some load balancing examples. For example, if I have a service deployed on multiple servers, how would I use this library to distribute loads?

There's RoundRobinLoadBalancerFactory that I tried, but don't know how I can make my services which are deployed on different machines to be managed by the balancer.

rhavyn commented 14 years ago

I'm not 100% sure exactly what you are looking for, so I'm going to offer a few pointers. Let me know if you need more details.

If you are hoping to use Norbert as a load balancer for your already existing services, unfortunately that isn't currently supported out of the box. Norbert's network client expects to be talking to a Norbert network server. I'd be happy to provide details for what you'd need to do to write your own load balancer for your network library though.

For an example of how to use the norbert client network library take a look here: https://github.com/rhavyn/norbert/blob/0.5_scala_2.8/examples/src/main/java/com/linkedin/norbert/javacompat/network/NorbertJavaNetworkClientMain.java. If you comment line 38 and uncomment line 39 and change it to use the round robin load balancer then that is an example of how to use the Norbert Java network client with the round robin load balancer.

Let me know if I could provide any additional information.

barryku commented 14 years ago

I got your sample working. The java server code is missing the part of adding a node to the client and set the client to the config, so I had to duplicate what you had in the scala version. I don't need to partition the work, so I still use NettyNetworkClient. The following is what I did,

  1. start 3 servers with a different node ID
  2. start a client (using sendMessage() to talk to one of the servers)
  3. take down server 1
  4. start another client

The sample worked fine that by step 4, the 2nd server was serving the request. I was able to set the node URL to the same (e.g. localhost:1000) for all three servers, and my test steps still work. What is the purpose of the url part of the node? I was hoping that I can point the URL to the place where I have my service deployed (e.g. http://myserver/myservice), but it only accepts server:port.

Thanks, Barry

rhavyn commented 14 years ago

I understand the question now.

There are two parts of Norbert, the cluster management/service discovery part and the client/server network application part. The reason that there is a url field is because the cluster management side of Norbert really doesn't care what that field is set to, it's up to the consumer of the information to decide. On the other hand, any client application needs to be able to parse that into a usable address to talk to and client/server framework provided with Norbert assumes that the url is in the format host:port.

Your problem, if I understand your follow up correctly, is you want to communicate with something other than a Norbert server. Unfortunately today that isn't possible with the Norbert client code, it only knows how to talk to the Norbert server code. The good news is you can still use whatever client technology you're currently using and still use Norbert's load balancing mechanism.

What you'll want to do is, instead of creating an instance of NettyNetworkClient, create an instance of ZooKeeperClusterClient. Then you'll need to create a ClusterListener that has a reference to the LoadBalancerFactory you want to use and whenever you get an event, call newLoadBalancer on the factory. Now you can put whatever you want in the url field of the Node, and whenever you want to send a request call nextNode on the LoadBalancer instance and use whatever your current client is to open (or use a cached, already open) connection to the url in the Node and send your request.

Does that make sense?

barryku commented 14 years ago

Thank you very much for your prompt response. I will give it a try of your suggestions when I get a chance. Barry