Here is the code that does that for the Fabio load balancer: https://github.com/fabiolb/fabio/blob/15565deb06bf2ef7a8b67f42e958c7b370bf29da/registry/consul/service.go
You’ll notice here that Fabio doesn’t actually query for all services that are running, just health checks that are passing. I think this makes sense, and you might want to use this strategy, since you might not want to direct traffic to services that are unhealthy. On the other hand this means fabio has no visibility into services that are failing their health checks but potentially should be routable.
That call will get you the services that are passing, after that fabio queries for the service tags here. This is where nomad puts the metadata about where those services can be found (ip/port etc).
Not sure if this can all be done in a single request, since the list services endpoint doesn’t contain the tag metadata that you need.
Additional details in response to comment:
This code uses a wait index and consul’s concept of watches. You can see that configured here. So there is still a very minor delay, but this request is not constant polling. It makes an outbound request to consul and hangs until consul has new changes to report. In practice this is very quick and has not led to latency issues for me (although they still technically exist, network request overhead, re-querying for tags, etc)
CLICK HERE to find out more related problems solutions.