Http client feign for microservices

Problems with calling RestTemplate

Let's first take a look at the code of the remote call initiated by RestTemplate:

String url = "http://userservice/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);

There are the following problems:

1. Poor code readability and inconsistent programming experience

2. URL s with complex parameters are difficult to maintain

 

Introduction, definition and use of Feign

 

 

The steps to use Feign are as follows:

1. Introduce dependencies:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId> 
</dependency>

2. Add annotations to the startup class of the microservices that need to be used to enable the Feign function:

 

 

3. Write Feign client:

@FeignClient("userservice")
public interface UserClient {
    @GetMapping("/user/{id}") 
    User findById(@PathVariable("id") Long id);
}

It is mainly based on SpringMVC annotations to declare remote call information, such as: Service name: userservice Request method: GET Request path: /user/{id} Request parameter: Long id Return value type: User

4. Replace RestTemplate with Feign client

 

 

 

 

 

 

Customize the configuration of Feign:

Feign runs a custom configuration to override the default configuration. The configuration that can be modified is as follows:

 

 

 

There are two ways to configure Feign logs:

Method 1: configuration file method

1. Take effect globally:

feign:
  client:
    config: 
      default: # Here default is the global configuration, if it is to write the service name, it is the configuration for a microservice
        loggerLevel: FULL #  log level 

2. Partial effect:

feign:
  client:
    config: 
      userservice: # Here default is the global configuration, if it is to write the service name, it is the configuration for a microservice
        loggerLevel: FULL #  log level 

Method 2: java code method, you need to declare a Bean in advance:

public class FeignClientConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; 
    }
}

1. Then if it is a global configuration, put it in the @EnableFeignClients annotation:

@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class) 

2. If it is a partial configuration, put it in the @FeignClient annotation:

@FeignClient(value = "userservice", configuration = FeignClientConfiguration.class) 

 

 

 

 

Fegin performance optimization:

The underlying client implementation of Feign:

URLConnection: default implementation, does not support connection pooling

Apache HttpClient: support connection pool

OKHttp: support connection pool

 

Therefore, optimizing the performance of Feign mainly includes:

Use a connection pool instead of the default URLConnection

log level, preferably basic or none

 

Feign adds HttpClient support:

 

1. Introduce dependencies:

<!--httpClient dependence on -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

2. Configure the connection pool

feign:
  client:
    config:
      default: # default global configuration
        loggerLevel: BASIC # Log level, BASIC is the basic request and response information 
  httpclient:
    enabled: true # Enable feign's support for HttpClient
    max-connections: 200 # maximum number of connections
    max-connections-per-route: 50 # Maximum number of connections per path

 

 

 

Feign's best practice and optimization

Method 1 (inheritance): Define a unified standard parent interface for the consumer's FeignClien and the provider's controller as a standard (not recommended

 

 

Method 2 (extraction): Extract Feign as an independent module, and put the interface-related POJO and default Feign configuration into this module for all consumers to use

 

 

 

The steps to implement Best Practice Method 2 are as follows:

1. First create a module named feign-api, and then introduce feign's starter dependency

2. Copy the UserClient, User, and DefaultFeignConfiguration written in order-service to the feign-api project

3. Introduce feign-api dependency in order-service

4. Modify all the import parts related to the above three components in order-service, and change them to import the package in feign-api

restart test

 

When the defined FeignClient is not in the scope of SpringBootApplication's scan package, these FeignClients cannot be used. There are two ways to solve it:

Method 1: Specify the package where FeignClient is located, and scan an entire package

@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

Method 2: Specify the FeignClient bytecode, scan the required client, and recommend using method 2 to achieve the effect of only using the required client

@EnableFeignClients(clients = {UserClient.class})

 

Tags: Microservices

Posted by FoTo50 on Fri, 25 Nov 2022 13:21:20 +1030