Add client support for Watches
It would be great if real-time notification of config changes (KV data changes) were possible on the client-side.
I believe this concept is supported in the "raw" Consult API via watches, however I don't see that concept supported by this library.
The idea is simple:
- Allow clients to register their own callbacks/watches with the Consul cluster
- The callback/watch will now execute when the cluster senses a change to config data (or anything really)
The idea is to allow GOSSIP to "do its thing" and update clients in real-time, rather than forcing clients to poll.
Hi
I also like use this feature but the implementation wouldn't be easy, Consul do not provide http api to register watches, currently I just adding watches by executing Consul agent commands from java Runtime.getRuntime().exec(...) so firslty we have to wait for exposing new http api methods in Consul :(
Consul do not provide http api to register watches
Yes. This is the only thing that stops me from implementation
Watches are implemented using blocking queries in the HTTP API. Agents automatically make the proper API calls to watch for changes and inform a handler when the data view has updated.
I believe we can find those HTTP commands using a simple sniffer proxy.
update: I created a simple http reverse proxy w/ logging using node.js, Check out this log :
Request /v1/kv/foo
{
"host": "127.0.0.1:8501",
"user-agent": "Go-http-client/1.1",
"accept-encoding": "gzip"
}
Response {
"content-type": "application/json",
"x-consul-index": "48",
"x-consul-knownleader": "true",
"x-consul-lastcontact": "0",
"date": "Sat, 15 Oct 2016 10:16:56 GMT",
"content-length": "88",
"connection": "close"
}
Request /v1/kv/foo?index=48
{
"host": "127.0.0.1:8501",
"user-agent": "Go-http-client/1.1",
"accept-encoding": "gzip"
}
Response {
"content-type": "application/json",
"x-consul-index": "221",
"x-consul-knownleader": "true",
"x-consul-lastcontact": "0",
"date": "Sat, 15 Oct 2016 10:17:13 GMT",
"content-length": "89",
"connection": "close"
}
Request /v1/kv/foo?index=221
{
"host": "127.0.0.1:8501",
"user-agent": "Go-http-client/1.1",
"accept-encoding": "gzip"
}
It seems that at first, the client looks for the current value of the key, after that, it queries the same key w/ a query string parameter named "index" that returned from the last result, at this point, the HTTP request is blocking until the key is updated...
update 2: Same thing happens for keyprefix:
Request /v1/kv//?recurse=
{
"host": "127.0.0.1:8501",
"user-agent": "Go-http-client/1.1",
"accept-encoding": "gzip"
}
Response {
"content-type": "application/json",
"x-consul-index": "221",
"x-consul-knownleader": "true",
"x-consul-lastcontact": "0",
"date": "Sat, 15 Oct 2016 10:20:22 GMT",
"content-length": "89",
"connection": "close"
}
Request /v1/kv//?index=221&recurse=
{
"host": "127.0.0.1:8501",
"user-agent": "Go-http-client/1.1",
"accept-encoding": "gzip"
}
(BTW, the request and responses that you see are the headers and not the body)
It's pretty easy to implement on this client, I managed to do so without any need to modify the client.
Good job @vgv and ecwid :+1:
below are sample code based on @shanielh explanation:
private static void longPolling(String serviceName){
long consulIndex = -1;
do{
QueryParams param =
QueryParams.Builder.builder()
.setIndex(consulIndex)
.build();
Response<List<HealthService>> healthyServices =
consulClient.getHealthServices(serviceName, true, param);
consulIndex = healthyServices.getConsulIndex();
List<HealthService> services = healthyServices.getValue();
for (HealthService healthyService : services) {
logger.info("Updated services info: {}", healthyService);
}
}while(true);
}
can support watch service now? rickfast's consul-client hava a class ServiceHealthCache support watch service.
Hi, I also started looking at this implementation and looking for watch service. Would it be implemented?