Spring-cloud-netflix: How to aggregate/map actuator endpoints through Zuul?

Created on 17 Feb 2017  路  16Comments  路  Source: spring-cloud/spring-cloud-netflix

I have couple of microservices, proxying through Zuul and registered in Eureka. Each microservice is dockerized and the only output point is Zuul proxy which explicitly routes each path to proper service. I wonder if there is any "proper" way to get to actuator endpoints in each microservice through Zuul proxy?
Things I figured out to handle this use case don't look much pretty:

  1. Expose all microservices. Don't specify zuul.ignored-services=* so the API will look like _http://127.0.0.1:8080/service1/api/v2/someApi_ and add mapping explicitly to expose just _http://127.0.0.1:8080/api/v2/someApi_. Then I can query health from _http://127.0.0.1:8080/service1/health_ but i'm exposing redundant api.
  2. Hardcode URLs to each endpoint of each microservice.
    zuul.routes.service1-health.path=/service1/health
    zuul.routes.service1-health.url=http://127.0.0.1:8001/health
  3. [Most disgusting solution, I guess] Create custom ZuulFilter which will catch actuator endpoint request and will try to query all services for this endpoint, aggregate results and return combined result from all services.
  4. Do same as 3 not through ZuulFilter but expose conditional endpoint (e.g /endpoints/{endpointName}) and go through all services, aggregate responses and also return combined result.
  5. Create something like zuul.routes.service1.service-path=/health property which will map route external path to some other path in each service.

Please tell if there is a better way to do this.

Thanks!

P.S. I wrote solution nr 4 and it works just perfect for my need :)

enhancement

Most helpful comment

It could be. I don't think a ZuulFilter is the necessarily the right place.

All 16 comments

There is no solution for this. Something like 3 or 4 is the only way to do this.

Don't you think it would be a handy feature? Especially in production environments.

It could be. I don't think a ZuulFilter is the necessarily the right place.

I agree. It would be quite tough and unreliable to do it there. Thats why I've chosen option 4.

If this isn't associated with zuul it should go in https://github.com/spring-cloud/spring-cloud-commons

I think it should be associated with zuul and use org.springframework.cloud.client.discovery.DiscoveryClient to retrieve all services and org.springframework.cloud.client.serviceregistry.Registration to exlude itself.
This functionality is not common for all services and should be located in one place.
As for me it is zuul responsibility to do such a logic.

You just agreed that it shouldn't be in a ZuulFilter. DiscoveryClient and Registration are part of spring-cloud-commons. I still think it should live there.

But then you could apply it to any service, which does not make sense for me.

What does it have to do with Netflix?

I guess it should be feature related to "proxy" or "router" abstraction. Zuul is an implementation of this abstraction.

Adding an "actuator endpoints aggregator from all services" feature should be associated with an "edge" service and not be available from other services.

Why? You could argue it SHOULDN'T be available at the edge. Why have it be public? It COULD be. I'm thinking it's an actuator endpoint that you have to enable, it wouldn't be auto-configured by default.

Yes, of course it should be optional. I've said this already.
What I'm saying that:

  1. This endpoint COULD be available at the edge.
  2. This endpoint SHOULD NOT be available elsewhere, because it will be redundant.

Maybe we're thinking of different approaches to do this.

My personal feeling is not to touch actuator, but do it like this:

Assume we have such services (all have actuator):

  1. edge (with zuul)
  2. registry (eureka)
  3. service1
  4. service2

edge.properties:

server.port=8080

z.r.s1.path=/s1/**
z.r.s1.service-id=service1

z.r.s2.path=/s2/**
z.r.s2.service-id=service2

Expected result:
https://127.0.0.1:8080/endpoints/health returning both service1/health and service2/health (for example as list)
https://127.0.0.1:8080/endpoints/metrics returning both service1/metrics and service2/metrics

Possible solution (working for me):

  1. In edge service create CONDITIONAL_ON_PROPERTY controller with /endpoints/{endpointName} endpoint which will serve /endpoints/health, /endpoints/env etc. for each actuator endpoint to collect.
  2. Configure which endpoints you want to serve with some properties.
  3. Create some "EndpointsAggregator" which will query all instances of all services for this exact endpoint
  4. Wrap all responses into some class which contains serviceId, instanceHost and the response itself.
  5. Return a list of these wrapped responses.

That's how I see it.
I've already implemented this and it seems to be working fine.

Waiting for your implementation variant.

OK, I don't want to argue about it anymore.

@zablvit I don't think this is a good idea of Zuul to be an endpoints aggregator of services behind it just because it has that information. :) I can give you an example: /hystrix.stream is also available on zuul, but hystrix aggregator is Turbine, not Zuul. :) Maybe creating separate monitoring service is a better solution?

This module has entered maintenance mode. This means that the Spring Cloud team will no longer be adding new features to the module. We will fix blocker bugs and security issues, and we will also consider and review small pull requests from the community.

Was this page helpful?
0 / 5 - 0 ratings