Service discovery with ZooKeeper

You can put the list of available Endpoints into a zNode in Apache ZooKeeper cluster, as a node tree or as a node value, like the following:

# (Recommended) When stored as a node tree:
# Note: Only child node values are used. i.e. Child node names are ignored.
- /myProductionEndpoints
  - /192.168.1.10_8080: 192.168.1.10:8080
  - /192.168.1.11_8080: 192.168.1.11:8080:100

# When stored as a node value:
- /myProductionEndpoints: 192.168.1.10:8080,192.168.1.11:8080:100

In the examples above, 192.168.1.10 and other IP strings are your servers’ IP addresses, 8080 is a service port number and 100 is a weight value. You can omit a weight value as it is optional.

Create a ZooKeeperEndpointGroup to retrieve this information:

import com.linecorp.armeria.client.endpoint.EndpointGroup;
import com.linecorp.armeria.client.zookeeper.ZooKeeperEndpointGroup;
import com.linecorp.armeria.client.zookeeper.ZooKeeperEndpointGroup.Mode;

EndpointGroup myEndpointGroup = new ZooKeeperEndpointGroup(
        /* zkConnectionStr */ "myZooKeeperHost:2181",
        /* zNodePath       */ "/myProductionEndpoints",
        /* sessionTimeout  */ 10000,
        /* mode            */ Mode.IN_CHILD_NODES /* or Mode.IN_NODE_VALUE */);

And then register it to the EndpointGroupRegistry, and specify it in a client URI:

import static com.linecorp.armeria.client.endpoint.EndpointGroupRegistry;
import static com.linecorp.armeria.client.endpoint.EndpointSelectionStrategy.WEIGHTED_ROUND_ROBIN;

EndpointGroupRegistry.register("myProductionGroup", myEndpointGroup, WEIGHTED_ROUND_ROBIN);
// Specify 'group:<groupName>' in the authority part of a client URI.
HelloService.Iface helloClient = Clients.newClient(
        "tbinary+http://group:myProductionGroup/hello", HelloService.Iface.class);

For more information, please refer to the API documentation of the com.linecorp.armeria.client.zookeeper package.

Automatic service registration

Use ZooKeeperUpdatingListener to register your server to a ZooKeeper cluster:

import com.linecorp.armeria.server.ServerListener;
import com.linecorp.armeria.server.zookeeper.ZooKeeperUpdatingListener;

// This constructor will use server's default host name, port and weight.
// Use the other constructors to override the defaults.
ServerListener listener = new ZooKeeperUpdatingListener(
        /* zkConnectionStr */ "myZooKeeperHost:2181",
        /* zNode           */ "/myProductionEndpoints",
        /* sessionTimeout  */ 10000);
server.addListener(listener);
server.start();
...

When your server starts up, ZooKeeperUpdatingListener will register the server automatically to the specified zNode as a member of the cluster. Each server will represent itself as an EPHEMERAL node, which means when a server stops or a network partition between your server and ZooKeeper cluster occurs, the node of the server that became unreachable will be deleted automatically by ZooKeeper. As a result, the clients that use a ZooKeeperEndpointGroup will be notified and they will update their endpoint list automatically so that they do not attempt to connect to the unreachable servers.

For more information, please refer to the API documentation of the com.linecorp.armeria.server.zookeeper package.