Setting timeout to OpenFeign client

3.8k Views Asked by At

I'm trying to setup a timeout to my feign clients when they try to access to other of my services. In order to test my circuit breaker method. This is my basic setup. I'm using spring-boot 3.0.2 and spring cloud version 2022.0.1

I have a edge-service project this is the pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>e-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>e-service</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2022.0.1</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>netflix-candidates</id>
            <name>Netflix Candidates</name>
            <url>https://artifactory-oss.prod.netflix.net/artifactory/maven-oss-candidates</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>

As you can see I have the spring-cloud-starter-openfeign dependency

This is my configuration in the application.properties

spring.application.name=edge-service
server.port=8080

feign.client.config.default.readTimeout=2000

Using this property feign.client.config.default.readTimeout=2000 it should be enough to set my readTimeout to 2 seconds. But for some reason is not working.

In my service where I'm calling to my FeignClient (ProxyServiceClient)

@Service
public class MovieServiceImpl implements MovieService {

    private final Logger logger = LoggerFactory.getLogger(MovieServiceImpl.class);

    @Autowired
    private ProxyServiceClient proxyServiceClient;

    @CircuitBreaker(name = "findHorroMovies", fallbackMethod = "findHorrorMoviesFallback")
    public ResponseDTO findAllHorroMovies() {

        ResponseDTO responseDTO = new ResponseDTO();

        List<MovieCatalogDTO> horroMovies = proxyServiceClient.findByGenre(Genre.HORROR);

        responseDTO.setMovieCatalogs(horroMovies);
        responseDTO.setMessage("Buuuuuhhhh");
        responseDTO.setSize(horroMovies.size());

        return responseDTO;
    }

    public ResponseDTO findHorrorMoviesFallback(Exception e) {
        logger.error(e.getMessage());
        ResponseDTO responseDTO = new ResponseDTO();
        List<MovieCatalogDTO> movieCatalogs = new ArrayList<>();
        responseDTO.setMovieCatalogs(movieCatalogs);
        responseDTO.setSize(0);
        responseDTO.setMessage("Buuuuuhhh (cached)");

        return responseDTO;

    }

}

And in my ProxyService I'm setting a sleep time of 3 seconds to trigger the timeout in every request

@RestController
public class MovieCatalogControllerImpl implements MovieCatalogController {

    @Autowired
    private MovieCatalogService movieCatalogService;

    @GetMapping("/movie-catalog")
    public List<MovieCatalog> findByGenre(@RequestParam Optional<Genre> genre) throws InterruptedException {

        Thread.sleep(3000);

        if(genre.isPresent()) {
            return movieCatalogService.findByGenre(genre.get());
        }
        return movieCatalogService.findAll();
    }
}

I'm doing some tests but it keeps taking more than 2 seconds without closing the connection. I don't know what could I been doing wrong. Hope you can help me.

I tried to add in my application.properties file the property

feign.client.config.default.readTimeout=2000

to set the readTimeout in 2 seconds, but is not working...I don't know if it has to be something with the version of spring-boot or spring-cloud. Because I remember this approach used to work in older projects.

1

There are 1 best solutions below

0
On BEST ANSWER

Okay, I found the solution. In the openfeign document there is an explanation where the default configuration in the application.properties has been changed

spring:
    cloud:
        openfeign:
            client:
                config:
                    feignName:
                        url: http://remote-service.com
                        connectTimeout: 5000
                        readTimeout: 5000
                        loggerLevel: full
                        errorDecoder: com.example.SimpleErrorDecoder
                        retryer: com.example.SimpleRetryer
                        defaultQueryParameters:
                            query: queryValue
                        defaultRequestHeaders:
                            header: headerValue
                        requestInterceptors:
                            - com.example.FooRequestInterceptor
                            - com.example.BarRequestInterceptor
                        responseInterceptor: com.example.BazResponseInterceptor
                        dismiss404: false
                        encoder: com.example.SimpleEncoder
                        decoder: com.example.SimpleDecoder
                        contract: com.example.SimpleContract
                        capabilities:
                            - com.example.FooCapability
                            - com.example.BarCapability
                        queryMapEncoder: com.example.SimpleQueryMapEncoder
                        micrometer.enabled: false

So I had to update this property

spring.cloud.openfeign.client.config.default.readTimeout=2000

instead of this

feign.client.config.default.readTimeout=2000

And that was the solution. I hope it can be helpful to someone facing the same problem as me :D.