ServiceResolverClient client = ServiceResolverClient.create(vertx, new KubeResolverOptions());
// Resolve a service endpoint
Future<Endpoint> fut = client.resolveEndpoint(ServiceAddress.of("the-service"));
fut.onSuccess(endpoint -> {
// Print physical servers details
List<ServerEndpoint> servers = endpoint.servers();
for (ServerEndpoint server : servers) {
System.out.println("Available server: " + server.address());
}
});
Vert.x Service Resolver
The Service Resolver library is a plugin that lets Vert.x clients call services using logical service names instead of network addresses. The service resolver is also able to perform client side load balancing with the usual strategies.
You can use a service resolver as a client to query a resolver or integrated natively with a Vert.x client.
Service resolver client
You can query a service resolver with the service resolver client.
You can also let the load balancer select nodes
ServiceResolverClient client = ServiceResolverClient.create(vertx, new KubeResolverOptions());
// Resolve a service endpoint
Future<Endpoint> fut = client.resolveEndpoint(ServiceAddress.of("the-service"));
fut.onSuccess(endpoint -> {
// Print physical servers details
List<ServerEndpoint> servers = endpoint.servers();
for (ServerEndpoint server : servers) {
System.out.println("Available server: " + server.address());
}
});
Client integration
The service resolver is integrated with the Vert.x HTTP and Web clients.
Getting started with the Vert.x HTTP Client
Given a resolver, you can configure a Vert.x HTTP Client to use it thanks to an HttpClientBuilder
.
HttpClient client = vertx.httpClientBuilder()
.withAddressResolver(resolver)
.build();
A service is addressed with a ServiceAddress
instead of a SocketAddress
.
ServiceAddress serviceAddress = ServiceAddress.of("the-service");
Future<HttpClientRequest> requestFuture = client.request(new RequestOptions()
.setMethod(HttpMethod.GET)
.setURI("/")
.setServer(serviceAddress));
Future<Buffer> resultFuture = requestFuture.compose(request -> request
.send()
.compose(response -> {
if (response.statusCode() == 200) {
return response.body();
} else {
return Future.failedFuture("Invalid status response:" + response.statusCode());
}
}));
Getting started with the Vert.x Web Client
Given a resolver, you can configure a Vert.x Web Client to use it thanks to an HttpClientBuilder
.
HttpClient httpClient = vertx.httpClientBuilder()
.withAddressResolver(resolver)
.build();
WebClient webClient = WebClient.wrap(httpClient);
A service is addressed with a ServiceAddress
.
ServiceAddress serviceAddress = ServiceAddress.create("the-service");
Future<HttpResponse<Buffer>> future = webClient
.request(HttpMethod.GET, new RequestOptions().setServer(serviceAddress))
.send();
Client side load balancing
The default load balancing behavior is round-robin, you can change the load balancer to use:
HttpClient client = vertx.httpClientBuilder()
.withAddressResolver(resolver)
.withLoadBalancer(LoadBalancer.LEAST_REQUESTS)
.build();
Service resolver implementations
The service resolver integrates with a few discovery services such as Kubernetes and DNS SRV records.
Kubernetes resolver
The Kubernetes resolver locates services within a Kubernetes cluster.
The Kubernetes resolver requires the Here is an example configuration of role and role binding for the |
KubeResolverOptions options = new KubeResolverOptions();
KubeResolver resolver = KubeResolver.create(options);
HttpClient client = vertx.httpClientBuilder()
.withAddressResolver(resolver)
.build();
The default resolver options values are loaded from the pod environment - KUBERNETES_SERVICE_HOST
- KUBERNETES_SERVICE_PORT
- /var/run/secrets/kubernetes.io/serviceaccount/token
- /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
- /var/run/secrets/kubernetes.io/serviceaccount/namespace
You can override these settings.
You can deal with ephemeral tokens using the tokenProvider
.
KubeResolverOptions options = new KubeResolverOptions();
KubeResolver resolver = KubeResolver.create(options)
.tokenProvider(() -> loadToken());
HttpClient client = vertx.httpClientBuilder()
.withAddressResolver(resolver)
.build();
The resolver calls the provider when it needs a fresh token. The token is cached by the resolver until it is detetected stale by the resolver (upon a 401
server response code).
Matching specific service ports
When a service exposes more than one port, the resolver retains only a single port, it might not be the expected port.
You can build a specific service address for a given service port number.
ServiceAddress serviceAddress = KubernetesServiceAddressBuilder
.of("the-service")
.withPortNumber(8080)
.build();
Or a given service port name.
ServiceAddress serviceAddress = KubernetesServiceAddressBuilder
.of("the-service")
.withPortName(portName)
.build();
SRV resolver
The SRV resolver uses DNS SRV records to resolve and locate services.
SrvResolverOptions options = new SrvResolverOptions()
.setServer(SocketAddress.inetSocketAddress(dnsPort, dnsServer));
AddressResolver resolver = SrvResolver.create(options);
HttpClient client = vertx.httpClientBuilder()
.withAddressResolver(resolver)
.build();