Search code examples
javaspringgraphqlmicroservicesnetflix-zuul

GraphQL and Zuul : WIll Graphql work as an rest endpoint with zuul as api gateaway


I already have a microservice based application running with Spring Cloud , and have zuul as an API gateway , but we are thinking of changing to Graphql instead of traditional Rest due to company usecases , hence I was thinking of creating graphql Api for each microservice , will this work , will zuul be able to handle rerouting and will Hysterix be able to perform fault tolerance while maintaining Hysterix Dashboard? .. has Anybody done this before?


Solution

  • UPDATE

    If you wanted to use Spring Boot GraphQL implementation that would reduce some of the overhead below. Looking into that as well.

    I'm working to figure this out myself right now, but here's the idea I am going for -- it might be a while before I can confirm it works, but here is my initial plan.

    Schematic https://i.sstatic.net/JiSb8.jpg

    Zuul ---> GraphQL (Apollo) ---> Various API Endpoints
    

    GraphQL (Apollo) allows you to specify your API endpoints. You could have Apollo point to your Zuul defined routes to those API endpoints or have Apollo point directly to the microservice.

    Connecting Apollo to your API/REST endpoint

    https://www.apollographql.com/docs/tutorial/data-source/

    Fail-Over/High Availability

    One additional consideration is how to handle fail-over/high availability. This part gets a bit tricky. There are three pieces to manage: (1) fail-over/HA for GraphQL, (2) fail-over/HA for your underlying microservice, (3) the circuit breaker works (ZuulFallbackProvider/Hystrix) [forgive me if that is wrong - still learning about Zuul] - and whether that should be implemented at the Gateway (Zuul) or API EndPoint or on both.

    (1) Failover/HA for GraphQL

    Use Apollo Federation https://www.apollographql.com/docs/apollo-server/federation/introduction/

    For each GraphQL schema or however you decide to split it - setup at least two GraphQL services per schema and put those behind a load balancer. Set your Apollo Gateway to point to the load balancer.

    https://www.apollographql.com/docs/apollo-server/federation/introduction/#managed-federation

    const gateway = new ApolloGateway({
      serviceList: [
        { name: 'accounts', url: 'http://localhost:4001' },
        { name: 'products', url: 'http://localhost:4002' },
        { name: 'reviews', url: 'http://localhost:4003' }
      ]
    });  
    

    (2) Failover/HA for your underlying microservice

    This piece I already assume you have setup with a load balancer (Ribbon or anything else) and the services are registered in Eureka with multiple instances.

    You might also have a fallback method here for a given REST request (e.g. read) - This fallback method works if you can reach this microservice still through the GraphQL service.

    Well what if you can't?! (1) Well if your other instance is up and working - no problems (2) Let's pretend all the services are out and the GraphQL service returns an error because it can't contact anything. So now to go to our third part of the question - Where do we put the circuit breakers?

    (3) Circuit Breakers

    Three levels of circuit breakers:

    (1) Keep your Zuul circuit breakers if for some reason any part of the request chain fails all the way down to the microservice a. In Zuul you will write your actions to happens when the circuit breaker is triggered b. Have the GraphQL Gateway point to a path that requires routing through your API gateway [THIS IS KEY!]. What is your Microservice is up and running, but the GraphQL Service the gateway is trying to route to is down?

       Client -> Zuul -> GraphQL Gateway -> Zuul -> GraphQL Service A Load Balancer -> Microservice A Load Balancer -> Microservice A
    

    It looks like this could be the solution they solved it with (will make more sense if you read the first two links):

    https://github.com/apollographql/apollo-server/pull/1807

    Hopefully this works! I'll find out soon myself.