SpringCloud Feign Load Balancing

Time: Column:Backend & Servers views:249

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.

SpringCloud Feign Load Balancing

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

  1. Create the microservicecloud-consumer-dept-80 (client) and microservicecloud-consumer-dept-feign microservices.

  2. Add Feign dependency in pom.xml of microservicecloud-consumer-dept-feign module:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
  1. 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 the microservicecloud-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);
}
  1. Clear Maven cache and install the dependencies.

mvn clean
mvn install
  1. Modify the Controller in microservicecloud-consumer-dept-feign to use DeptClientService:

@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);
    }
}
  1. 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:

  1. NONE: No information is logged.

  2. BASIC: Logs only the request method, URL, response status code, and execution time.

  3. HEADERS: Logs all the information from BASIC, plus request and response headers.

  4. 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.