Service registration for discovery
Table of contents
- ZooKeeper-based service registration with ZooKeeperUpdatingListener
- Eureka-based service registration with EurekaUpdatingListener
- Consul-based service registration with ConsulUpdatingListener
You can use ServerListener
to register the information of Armeria servers when they start so that
a client uses the information to distribute its requests to the servers autonomously, unlike
traditional server-side load balancing where the requests go through a dedicated load balancer such as
L4 and L7 switches.
Armeria provides 2 ServerListener
implementations for service registration:
ZooKeeperUpdatingListener
which registers to ZooKeeper as an ephemeral node.EurekaUpdatingListener
which registers to Eureka.
ZooKeeper-based service registration with ZooKeeperUpdatingListener
First, You need the armeria-zookeeper3
dependency:
dependencies {
implementation platform('com.linecorp.armeria:armeria-bom:1.31.3')
...
implementation 'com.linecorp.armeria:armeria-zookeeper3'
}
Then, use ZooKeeperUpdatingListener
and ZooKeeperRegistrationSpec
to register your server
to a ZooKeeper cluster:
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.zookeeper.ZooKeeperRegistrationSpec;
import com.linecorp.armeria.server.zookeeper.ZooKeeperUpdatingListener;
String zkConnectionStr = "myZooKeeperHost:2181";
String znodePath = "/myProductionEndpoints";
String serviceName = "catalog";
ZooKeeperRegistrationSpec registrationSpec =
ZooKeeperRegistrationSpec.curator(serviceName);
ZooKeeperUpdatingListener listener =
ZooKeeperUpdatingListener.builder(zkConnectionStr, znodePath, registrationSpec)
.sessionTimeoutMillis(10000)
.build();
Server server = ...
server.addListener(listener);
server.start();
The ZooKeeperRegistrationSpec
is used to convert the information of your server to a binary
representation. The ZooKeeperUpdatingListener
registers the binary representation to the specified
znode as a member of the cluster when your server starts up. 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.
ZooKeeperRegistrationSpec.curator()
uses the format of
Curator Service Discovery which is compatible
with Spring Cloud Zookeeper.
You can use ZooKeeperRegistrationSpec.serverSets()
that applies the format of
Finagle ServerSets.
If you want to use your own format, you can implement the ZooKeeperRegistrationSpec
.
In the example above, we used the ZooKeeper connection string("myZooKeeperHost:2181"
) to connect to
the ZooKeeper cluster. Instead, you can use an existing
CuratorFramework
instance.
import org.apache.curator.framework.CuratorFramework;
CuratorFramework client = ...
String znodePath = ...
ZooKeeperRegistrationSpec registrationSpec = ...
ZooKeeperUpdatingListener listener =
ZooKeeperUpdatingListener.builder(client, znodePath, registrationSpec)
.build();
Server server = ...
server.addListener(listener);
server.start();
For more information, please refer to the API documentation of the com.linecorp.armeria.server.zookeeper package.
Eureka-based service registration with EurekaUpdatingListener
First, You need the armeria-eureka
dependency:
dependencies {
implementation platform('com.linecorp.armeria:armeria-bom:1.31.3')
...
implementation 'com.linecorp.armeria:armeria-eureka'
}
Then, use EurekaUpdatingListener
to register your server to the Eureka:
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.eureka.EurekaUpdatingListener;
EurekaUpdatingListener listener =
EurekaUpdatingListener.of("https://eureka.com:8001/eureka/v2");
ServerBuilder sb = Server.builder();
sb.serverListener(listener);
sb.build().start();
If you want to specify the properties
of the Server
, use EurekaUpdatingListenerBuilder
:
import com.linecorp.armeria.server.eureka.EurekaUpdatingListenerBuilder;
EurekaUpdatingListenerBuilder builder =
EurekaUpdatingListener.builder("https://eureka.com:8001/eureka/v2")
.instanceId("i-00000000")
.hostname("armeria.service.1")
// If ipAddr is not specified, it's automatically filled
// using SystemInfo.defaultNonLoopbackIpV4Address().
.ipAddr("192.168.10.10")
.vipAddress("armeria.service.com:8080");
EurekaUpdatingListener listener = builder.build();
ServerBuilder sb = Server.builder();
sb.serverListener(listener);
sb.build().start();
For more information, please refer to the API documentation of the com.linecorp.armeria.server.eureka package.
Consul-based service registration with ConsulUpdatingListener
First, You need the armeria-consul
dependency:
dependencies {
implementation platform('com.linecorp.armeria:armeria-bom:1.31.3')
...
implementation 'com.linecorp.armeria:armeria-consul'
}
Then, use ConsulUpdatingListener
to register your server to the Consul:
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.consul.ConsulUpdatingListener;
ConsulUpdatingListener listener =
ConsulUpdatingListener.of("http://my-consul.com:8500", "my-service");
ServerBuilder sb = Server.builder();
sb.serverListener(listener);
sb.build().start();
If you want to specify an HTTP check or
tags to the Server
,
use ConsulUpdatingListenerBuilder
:
import com.linecorp.armeria.server.consul.ConsulUpdatingListenerBuilder;
ConsulUpdatingListenerBuilder builder =
ConsulUpdatingListener.builder("http://my-consul.com:8500", "my-service")
.check("http://my.hostname.local:8080/internal/l7check")
.tags("production", "v1");
ConsulUpdatingListener listener = builder.build();
ServerBuilder sb = Server.builder();
sb.serverListener(listener);
sb.build().start();
For more information, please refer to the API documentation of the com.linecorp.armeria.server.consul package.