Alfred Zhong
Alfred Zhong

Reputation: 7081

GRPC loadbalancer example

I am trying to build server set management mechanism with load balancing using GRPC/Java.

By looking at the API doc, there are classes like: LoadBalancer, RoundRobinLoadBalancerFactory, etc.

By looking at the names, it seems like they should do what I want to do. However, I couldn't find any code examples using these class even I googled very hard.

On the other hand, I found some Finagle/Thrift examples like this: https://github.com/benjumanji/finagle-serverset-example

I am wondering if anyone can share some working GRPC examples? Thanks!

Upvotes: 4

Views: 3787

Answers (3)

We just released a very simple example that can be found here: https://github.com/cloudtrust/lbclient/blob/master/grpc/staticResolver.go

package grpc

import (
"google.golang.org/grpc/naming"
)

type staticResolver struct{
    updates []*naming.Update
}

type staticWatcher struct {
    updates chan []*naming.Update
}

func NewStaticResolver(addr []string) naming.Resolver {
    var ups []*naming.Update
    for _,a := range addr {
        ups = append(ups, &naming.Update{naming.Add, a, ""})
    }
    return &staticResolver{ups}
}

func (w *staticWatcher) Next() ([]*naming.Update, error) {
    return <-w.updates, nil
}

func (w *staticWatcher) Close() {
    close(w.updates)
}

func (r *staticResolver) Resolve(target string) (naming.Watcher, error) {
    var ch chan []*naming.Update = make(chan []*naming.Update, 1)
    ch <- r.updates
    return &staticWatcher{ch}, nil
}

We hope this could help you, feel free to ask if you need anything.

Upvotes: -1

Peter
Peter

Reputation: 167

I've just found a Java version example from Kidong Lee's github repository: https://github.com/mykidong/grpc-java-load-balancer-using-consul/blob/master/src/test/java/io/shunters/grpc/component/grpc/HelloWorldClientWithNameResolver.java

/**
 * Consul NameResolver Usage.
 *
 *
 * @param serviceName consul service name.
 * @param consulHost consul agent host.
 * @param consulPort consul agent port.
 * @param ignoreConsul if true, consul is not used. instead, the static node list will be used.
 * @param hostPorts the static node list, for instance, Arrays.asList("host1:port1", "host2:port2")
 */
public HelloWorldClientWithNameResolver(String serviceName,
                                        String consulHost,
                                        int consulPort,
                                        boolean ignoreConsul,
                                        List<String> hostPorts) {

    String consulAddr = "consul://" + consulHost + ":" + consulPort;

    int pauseInSeconds = 5;

    channel = ManagedChannelBuilder
            .forTarget(consulAddr)
            .loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance())
            .nameResolverFactory(new ConsulNameResolver.ConsulNameResolverProvider(serviceName, pauseInSeconds, ignoreConsul, hostPorts))
            .usePlaintext(true)
            .build();

    blockingStub = GreeterGrpc.newBlockingStub(channel);
}

And you can find more examples from this repo.

Upvotes: 0

Kun  Zhang
Kun Zhang

Reputation: 629

gRPC LoadBalancer works with NameResolver. NameResolver emits addresses to LoadBalancer, and LoadBalancer makes decisions about making connections (Subchannels) and picking a Subchannel for each request.

A NameResolver and/or a LoadBalancer can be set to ManagedChannelBuilder to be used for a Channel.

While the interfaces are there, there aren't many stock implementations, rather than the basic DnsNameResolver and RoundRobinLoadBalancer. PickFirstBalancerFactory is the default "LoadBalancer" that actually doesn't do balancing.

If you have an address that has multiple addresses in DNS, you will observe round-robin behavior when using RoundRobinLoadBalancer. However, I guess you want to get the addresses from some service discovery system such as ZooKeeper. You will need to implement a NameResolver for that. If you are familiar with the discovery system of you choice, it shouldn't be hard.

Upvotes: 4

Related Questions