Spring Cloud Ribbon and Spring Cloud Hystrix implement client-side load balancing and service call protection using circuit breakers in microservices. These two frameworks are widely used in various microservices, including business-related services and infrastructure services (such as gateways). In practice, these frameworks are often used together. So, is there a higher-level abstraction that integrates both of these basic tools? Yes, that's where Spring Cloud Feign comes in. Built on Netflix Feign, Spring Cloud Feign not only integrates the functionalities of Ribbon and Hystrix but also offers a declarative way to define Web service clients.
1. What is Feign?
Feign is a declarative Web Service client. It simplifies writing Web Service clients by allowing you to define an interface and annotate it. Feign also supports JAX-RS standard annotations. Additionally, Feign supports pluggable encoders and decoders. Spring Cloud provides a wrapper around Feign, enabling it to support Spring MVC annotations and HttpMessageConverters
(for converting HTTP requests/responses to Java objects). Feign can be combined with Eureka and Ribbon to support load balancing. For more details, you can visit the official GitHub page: OpenFeign/feign.
2. What Can Feign Do?
Feign makes it easier to write Java HTTP clients. When using Ribbon and RestTemplate, the RestTemplate provides a wrapper for HTTP requests, forming a templated approach for service calls. In practice, since services may have multiple dependencies, an interface might be called in multiple places. Therefore, developers often encapsulate client classes for each microservice to manage these dependencies.
Feign takes this further by helping us define and implement service interface calls. With Feign, you only need to create an interface and annotate it. (Previously, @Mapper
annotations were added to DAO interfaces; now @FeignClient
annotations are added to microservice interfaces.) This simplifies the development process by automatically binding service provider interfaces when using Spring Cloud Ribbon.
3. Example
Create the
microservicecloud-consumer-dept-80
(client) andmicroservicecloud-consumer-dept-feign
microservices.Add Feign dependency in
pom.xml
ofmicroservicecloud-consumer-dept-feign
module:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
Modify the
microservicecloud-api
module (the common module, which can be used by other subsystems).Modify
pom.xml
:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
Add the
DeptClientService
interface in themicroservicecloud-api
module and its methods (which match the provider's interface). Add@FeignClient
annotation on the client side.
@FeignClient(value = "MICROSERVICECLOUD-DEPT") public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public boolean add(Dept dept); }
Clear Maven cache and install the dependencies.
mvn clean mvn install
Modify the Controller in
microservicecloud-consumer-dept-feign
to useDeptClientService
:
@RestController public class DeptController_Consumer { @Autowired private DeptClientService service; @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return this.service.get(id); } @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return this.service.list(); } @RequestMapping(value = "/consumer/dept/add") public Object add(Dept dept) { return this.service.add(dept); } }
Enable Feign support in the main configuration class of
microservicecloud-consumer-dept-feign
using@EnableFeignClients
annotation:
@EnableFeignClients(basePackages = {"com.zzx.springcloud"}) public class DeptConsumer80_Feign_App { }
4. Request Compression
Spring Cloud Feign supports GZIP compression for requests and responses to reduce performance overhead during communication. You can enable this functionality with two configuration parameters:
feign.compression.request.enabled=true feign.compression.response.enabled=true
Additionally, you can fine-tune request compression settings, such as defining the MIME types to compress and setting a size threshold. Only requests larger than this size will be compressed:
feign.compression.request.enabled=true # Default MIME types for compression feign.compression.request.mime-type=text/xml,application/xml,application/json feign.compression.request.min-request.size=2048
5. Logging Configuration
Spring Cloud Feign creates a feign.Logger
instance for each client annotated with @FeignClient
. This logger can be configured to output detailed debug logs to help analyze the specifics of Feign requests. You can enable debug logs for a specific Feign client by configuring logging.level
in the application.yml
file:
logging.level.com.zzx.springcloud.DeptClientService=DEBUG
By default, the Logger.Level
is set to NONE
, meaning no request details are logged. You can adjust the logging level globally by creating a Logger.Level
bean in the main class or in a configuration class. You can then apply this configuration to individual Feign clients:
@Configuration public class FullLogConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } } @FeignClient(name = "", configuration = FullLogConfiguration.class) public interface XxxClient { }
There are four possible Logger.Level
settings:
NONE: No information is logged.
BASIC: Logs only the request method, URL, response status code, and execution time.
HEADERS: Logs all the information from
BASIC
, plus request and response headers.FULL: Logs all request and response details, including headers, body, and metadata.
6. Conclusion: Feign Integrates with Ribbon
Feign integrates Ribbon to manage the service list for MicroServiceCloud-Dept
and implements client-side load balancing using round-robin. Unlike Ribbon, Feign allows for a declarative approach to defining service bindings, making service calls simple and elegant. The fallback mechanism in Feign is handled through Hystrix, which is explained separately.