Introduction
Feign simplifies REST client development by abstracting away the underlying HTTP communication details. Instead of manually constructing URLs, handling parameter concatenation, and managing HTTP requests, Feign allows developers to define service calls as simple interface methods that resemble Spring MVC controller endpoints.
This declarative approach means you write interface definitions, and Feign handles the implementation at runtime. The framework integrates seamlessly with service discovery (like Eureka), load balancing (via Ribbon), and circuit breakers (via Hystrix).
Getting Started
Key Steps
Add Feign dependency to your project Enable Feign clients in your Spring Boot application Create a Feign client interface with service endpoint definitions Inject and invoke the client interface in your service layer
Adding the Feign Dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
Enabling Feign in Your Application
package com.example.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableFeignClients
@SpringCloudApplication
public class ConsumerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerServiceApplication.class);
}
}
The @SpringCloudApplication annotation combines three commonly used annotations in microservice applications: @SpringBootApplication, @EnableDiscoveryClient, and @EnableCircuitBreaker.
Creating a Feign Client Interface
The Feign interface tells the framework which service to call, what endpoint to hit, and what parameters to pass:
package com.example.consumer.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("user/{id}")
String queryById(@PathVariable("id") Long id);
}
Invoking the Feign Client
@Autowired
private UserClient userClient;
@GetMapping("{id}")
public String queryById(@PathVariable("id") Long id) {
return userClient.queryById(id);
}
Troubleshooting Connection Timeouts
Error: Request Processing Failed
Request processing failed; nested exception is feign.RetryableException: Read timed out executing GET
java.net.SocketTimeoutException: Read timed out
This timeout error occurs when the microservice response takes longer than the default timeout threshold. By default, Ribbon (the load balancer integrated with Feign) sets both connection and read timeouts to 1 second, which is often insufficient for production environments.
Ribbon Configuration Options
The following Ribbon properties control timeout behavior:
ribbon.ConnectTimeout: Maximum time to wait for a connection to establish (default: 1000ms) ribbon.ReadTimeout: Maximum time to wait for a response after connection (default: 1000ms) ribbon.OkToRetryOnAllOperations: Whether to retry failed requests ribbon.MaxAutoRetriesNextServer: Number of retries on different server instances ribbon.MaxAutoRetries: Number of retries on the current instance
Solution: Increase Timeout Values
Add the following configuration to your application.yml file:
ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
Setting both values to 60 seconds provides adequate time for slower service responses.
Integrating Feign with Hystrix Circuit Breaker
Feign includes built-in support for Hystrix circuit breakers, which prevent cascade failures when a service becomes unavailable.
Enabling Hystrix for Feign
By default, Hystrix support in Feign is disabled. Enable it in your configuration:
feign:
hystrix:
enabled: true
Creating a Fallback Implementation
When a service call fails, the fallback method provides a graceful degradation response:
package com.example.consumer.client;
import org.springframework.stereotype.Component;
@Component
public class UserClientFallback implements UserClient {
@Override
public String queryById(Long id) {
return "Service temporarily unavailable. Please try again later.";
}
}
Associating Fallback with the Client Interface
package com.example.consumer.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(
value = "user-service",
fallback = UserClientFallback.class
)
public interface UserClient {
@GetMapping("user/{id}")
String queryById(@PathVariable("id") Long id);
}
The fallback class must implement the same interface and be registered as a Spring bean (@Component annotation).
Request Compression
Spring Cloud Feign supports GZIP compression for both requests and responses, reducing network bandwidth usage and improivng performance.
Basic Compression Configuration
feign:
compression:
request:
enabled: true
response:
enabled: true
Advanced Compression Settings
feign:
compression:
request:
enabled: true
mime-types: text/html,application/xml,application/json
min-request-size: 2048
response:
enabled: true
The mime-types property specifies which content types should be compressed, and min-request-size defines the minimum payload size (in bytes) required before compression kicks in.
Configuring Feign Logging
Standard logging configurations do not apply to Feign clients by default. Since Feign creates new logger instances for each proxied client, you must explicitly configure the logging level.
Setting Package-Level Logging
logging:
level:
com.example: debug
Defining Feign Log Level Configuration
package com.example.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
Feign supports four logging levels:
NONE: No logging output (default) BASIC: Logs the HTTP method, URL, response status code, and execution time HEADERS: Includes request and response headers in addition to BASIC information FULL: Complete request and response details, including headers, body, and metadata