Search code examples
javaspring-cloud-netflixhystrixopenfeign

Microservice feign infinite loop of invocations?


I am confused about how an infinite loop of feign calls might behave. An example: Assume I have 2 APIs, A & B. if I call API A, which in turn calls API B via a feign HTTP call, which in turn calls API A again via feign, will it recognize this and break the call chain?

Quick flowchart of calls: A -> B -> A -> B ... Repeat infinitely?

I have not tried this code, it is just an idea。 But I am assuming that spring-cloud-starter-feign will provide some methods to resolve this problem? Is this assumption correct?

    @PostMapping(RestJsonPath.API_A)
    ResponseEntity<byte[]> apiA();

    @PostMapping(RestJsonPath.API_B)
    ResponseEntity<byte[]> apiB();

Will it execute until it times out or hystrix will stop it?


Solution

  • TL;DR:

    Feign will keep the connection open on the initial request from A to B until the pre-configured timeout kicks in. At this point, Feign will time out the request and if you have specified a Hystrix fallback, Spring will use your Hystrix fallback as the response.

    Explanation:

    spring-boot-starter-feign provides an abstraction layer for writing the HTTP request code. It will not handle potential loops or cycles in your code.

    Here is an example spring boot feign client from their tutorials website for demonstration:

    @FeignClient(value = "jplaceholder",
            url = "https://jsonplaceholder.typicode.com/",
            configuration = ClientConfiguration.class,
            fallback = JSONPlaceHolderFallback.class)
    public interface JSONPlaceHolderClient {
    
        @RequestMapping(method = RequestMethod.GET, value = "/posts")
        List<Post> getPosts();
    
    
        @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
        Post getPostById(@PathVariable("postId") Long postId);
    }
    

    Notice first that this is an interface - all the code is auto generated by Spring at startup time, and that code will make RESTful requests to the urls configured via the annotations. For instance, the 2nd request allows us to pass in a path variable, which Spring will ensure makes it on the URL path of the outbound request.

    The important thing to stress here is that this interface is only responsible for the HTTP calls, not any potential loops. Logic using this interface (which I can inject to any other Spring Bean as I would any other Spring Bean), is up to you the developer.

    Github repo where this example came from.

    Spring Boot Docs on spring-boot-starter-openfeign.

    Hope this helps you understand the purpose of the openfeign project, and helps you understand that it's up to you to deal with cycles and infinite loops in your application code.

    As for Hystrix, that framework comes in to play (if it is enabled) only if one of these generated HTTP requests fails, whether it's a timeout, 4xx error, 5xx error, or a response deserialization error. You configure Hystrix, as a sensible default or fallback for when the HTTP request fails.

    This is a decent tutorial on Hystrix.

    Some points to call out is that a Hystrix fallback must implement your Feign client interface, and you must specify this class as your Hysterix fallback in the @FeignClient annotation. Spring and Hystrix will call your Hystrix class automatically if a Feign request fails.