nats.java
nats.java copied to clipboard
Add better DNS resolution if possible
[Idea|Proposal] So currently, nats uses the net package to create a TCP connection to the (NATS) server. The current implementation basically takes the first IP from the domain name and uses it to create a TCP connection. For users that can’t implement different loadbalancing techniques through the DNS, using the first IP from the record is kind of a bummer and kind of forces the servers to have multiple domains (as only the first IP is used).
What would be really cool, is that before or while creating the TCP connection to the server, the dns resolution returns all the IPs and uses them as nats server endpoints to connect, enabling reconnecting to all the IPs in the record.
Let me know what you guys think!
You can use io.nats.client.impl.DataPort
and override connect.
But io.nats.client.impl.NatsConnection
is package class, so .........
I have a solution.
package io.nats.client.impl;
import XXXX.registry.RegistryClient;
import XXXX.registry.RegistryException;
import XXXX.registry.ServiceMeta;
import io.nats.client.Options;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
/**
* Use io.nats.client.impl package to access package class io.nats.client.impl.NatsConnection
*/
public final class NatsServiceDiscoveryDataPort extends SocketDataPort {
private static final Map<Options, RegistryClient> clients = new HashMap<>();
/**
* Register registry client
*
* @param options registry client target options
* @param registryClient registry client instance
*/
public static synchronized void registerRegistryClient(Options options, RegistryClient registryClient) {
if (Objects.nonNull(clients.putIfAbsent(options, registryClient))) {
throw new IllegalArgumentException("Exist registry client " + options.getConnectionName());
}
}
/**
* Unregister registry client
*
* @param options registry client target options
*/
public static synchronized void unregisterRegistryClient(Options options) {
clients.remove(options);
}
@Override
public void connect(String serverURI, NatsConnection conn, long timeoutNanos) throws IOException {
RegistryClient registryClient = clients.get(conn.getOptions());
if (registryClient == null) {
throw new IllegalStateException("Not found registry client for nats connection");
}
try {
URI uri = new URI(serverURI);
Optional<ServiceMeta> serviceMeta = registryClient.getDiscovery().getService(uri.getHost()); // add your balance logic code to here
if (serviceMeta.isPresent()) {
serverURI = uri.getScheme() + "://" + serviceMeta.get().getHost() + ":" + serviceMeta.get().getPort();
} else {
throw new RuntimeException("Not found nats service " + uri.getHost());
}
} catch (RegistryException | URISyntaxException e) {
throw new RuntimeException(e);
}
super.connect(serverURI, conn, timeoutNanos);
}
}
thanks felix, i have to do some maintenance on the library next week and will look at adding this.
ugh, forgot to look for 2.6.6, i will try to get this in my brain next time
This is supported by the users ability to override the list of servers to connect to.