I am trying to fulfill the same requirement: I have a Java service that should choose a leader, and I do not have the health settings configured in Consul.
Using LeaderElectionUtil in Consul-client is problematic, because if all the reasons mentioned above. Unfortunately, it is also impossible to configure LeaderElectionUtil , because all its internal actions are performed using private methods (it should have used protected and allow users to override session creation, for example).
I tried to implement "Service Registration" as described in "Basic Use - Example 1" in the README consul client, but calling AgentClient.pass() always changes the exception for me.
So, my solution - this is exactly what you indicated - do a session with TTL and update it until the service is up and running.
Here's my implementation, which requires the user to also register a callback, which is used to check if the service is valid for renewal, just in case:
public class SessionHolder implements Runnable { private static final String TTL_TEMPLATE = "%ss"; private Consul client; private String id; private LinkedList<Supplier<Boolean>> liveChecks = new LinkedList<>(); private long ttl; private boolean shutdown = false; public SessionHolder(Consul client, String service, long ttl) { this.client = client; this.ttl = ttl; final Session session = ImmutableSession.builder() .name(service) .ttl(String.format(TTL_TEMPLATE, ttl)) .build(); id = client.sessionClient().createSession(session).getId(); Thread upkeep = new Thread(this); upkeep.setDaemon(true); upkeep.start(); } public String getId() { return id; } public void registerKeepAlive(Supplier<Boolean> liveCheck) { liveChecks.add(liveCheck); } @Override public synchronized void run() {
Then the choice of a leader is more or less simple than:
if (consul.keyValueClient().acquireLock(getServiceKey(service), currentNode, sessionHolder.getId())) return true;
One thing that needs to be remembered is that if the session ends without clearing (which I do above in SessionHolder.close() ), the consul's lock-delay function will prevent the selection of a new leader for about 15 seconds (by default, which unfortunately, the Consul client does not offer an API for change).
To solve this problem, in addition to making sure that the final services are cleaned after themselves, as shown above, I also guarantee that the service maintains its leadership position for the minimum time necessary to release the leadership when no longer using it, calling consul.keyValueClient().releaseLock() . For example, I have a cluster service in which we select a leader to read data updates from an external RDBMS (which are then distributed directly to the cluster, and not every node, reloading all the data). Since this is done through a survey, each node will try to be elected before the poll, and if it is elected, it will test the database, distribute the update, and resign. If after this a failure occurs, delay-lock will not prevent another node from being polled.