Feign of spring cloud, service communication (declarative REST client)

RestTemplate is used in the previous study of calling between micro services. This chapter will learn Feign to communicate between services

FeignClient simplifies the writing of requests and selects which service to use for consumption through dynamic load. All this is realized by Spring dynamic configuration. We don't care about these, just use the method. In addition, the writing is simplified. The RestTemplate also needs to write the server IP information, etc., while FeignClient does not

Fegin remote call

Feign use

Feign is a declarative http client. Its function is to help us send http requests gracefully

rely on

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

Enable Feign function

//Add @ EnableFegin to the startup class
@EnableFeignClients
@SpringBootApplication
public class OrderServiceApplication{
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class);
    }

Write Feign client

// Define Feign call service interface
@FeignClient("userservice")
public interface UserServiceFeign {
    // The url path corresponds to the interface path of userservice
    // Parameters correspond to userservice interface parameters
    @GetMapping("user/{id}")
    UserEntity getUser(@PathVariable String id);
}

The remote call information is mainly declared based on the annotation of spring MVC:

  • Service Name: userservice
  • Request method: GET
  • Request path: / user/{id}
  • Request parameter: String id
  • Return value type: UserEntity

Specific parameter values can be modified according to their own conditions

The controller uses feign to call the userservice service service

@RestController
@RequestMapping("order")
public class OrderController {
	//Injection defined feign interface
    @Autowired
    private UserServiceFeign userServiceFeign;

    @RequestMapping("/{id}")
    public OrderEntity getOrder(@PathVariable String id){
        OrderEntity order = queryOrder(id);
        // Get user information by calling userservice through Feign
        UserEntity userEntity = userServiceFeign.getUser(id);
        order.setUser(userEntity);
        return order;
    }
}

Access: ip:port/order/001, get the correct response result, and successfully query the data in userservice

Custom configuration

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

typeeffectexplain
feign.Logger.LevelModify log levelIt includes four types: NONE, BASIC, HEADERS and FULL
feign.codec.DecoderParser for response resultsParse the result of the http remote call, for example, parse the json string as a java object
feign.codec.EncodeRequest parameter codeSet http request parameter encoding
feign.ContractSupported annotation formatsThe default is the annotation of spring MVC
feign.RetryerFailure retry mechanismThe retry mechanism for request failure is not available by default. Ribbon retry can be used

Generally, we only configure the log level

Modify log level

Method 1: configuration file method

  • Global validation
feign:
  client:
    config:
      default: # default here indicates global configuration. If it is a service name, it specifically refers to the configuration when accessing the service
        loggerLevel: FULL # log level
  • Partial effectiveness
feign:
  client:
    config:
      userservice: # default here indicates global configuration. If it is a service name, it specifically refers to the configuration when accessing the service
        loggerLevel: FULL # log level

Mode 2: java code mode, declaring beans

@Configuration
public class FeignClientConfiguration {

    @Bean
    public Logger.Level feignLogLevel(){
        // Configure log level
        return Logger.Level.FULL;
    }
}
  • Global configuration
/**
Global configuration log level, on feign Annotation(@EnableFeignClients)Add attribute to defaultConfiguration
/*
@EnableFeignClients(defaultConfiguration = {FeignClientConfiguration.class})
@SpringBootApplication
public class OrderServiceApplication{
}
  • Local configuration
/**
Configure the log level in a specific service, and add the attribute configuration = FeignClientConfiguration.class in @ FeignClient
*/
@FeignClient(value = "userservice",configuration = {FeignClientConfiguration.class})
public interface UserServiceFeign {
    @RequestMapping("user/{id}")
    UserEntity getUser(@PathVariable String id);
}

Note: during log configuration, the console did not print the log as expected

Reason: logback log level is not configured. Refer to the blog post for solutions: https://blog.csdn.net/qq_38668544/article/details/120268110

Add the following to application.yml

logging:
  level:
    com:
      cloud: debug #com.cloud is the package path

After configuration, the FULL level log is printed successfully, as shown in the following figure:

Feign performance optimization

Implementation of Feign underlying client:

  • URLConnection: it is implemented by default and does not support connection pool

The creation and destruction of connections consume resources

  • Apache HTTPClient: support connection pool
  • OKHttp: support connection pool

Therefore, feign optimization mainly includes:

  • Use the connection pool instead of the default URLConnection
  • Log level, preferably basic or none

Connection pool configuration

Using HTTPClient

Introduce dependency

 <!-- feign Connection pool dependency -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

application.yml configuration related support

# Configuration of feign
feign:
  httpclient:
    enabled: true # Enable feign's support for HTTP client
    max-connections: 200 # maximum connection
    max-connections-per-route: 50 # Maximum connections per path

Best practices

Method 1 (inheritance): define the agreed parent interface for the FeignClient of the consumer and the Controller of the provider as the standard

Because Feign client defines the method of calling interface and Controller, the code similarity is very high, so a parent interface can be extracted from this part as the standard

Disadvantages: tight coupling

Method 2 (extraction): extract FeignClient as a Feign API, and put the POJO related to the interface and the default Feign configuration in the module for consumers to use

Disadvantages: introducing feign API is equivalent to introducing all relevant feign configurations of the whole microservice project

Note: feign API is introduced in this way, and relevant components will not be scanned and added to the IOC container. The reason is that the default package scanning range of springboot is the current package and its sub packages

Solution:

@EnableFeignClients(basePackages = "XXXXXX")
// XXXXX is the package path of feignClient in feign API

perhaps

@EnableFeignClients(clients = UserServiceFeign.class)
// Specify a feignClient

You can choose according to the actual items

Tags: Spring Cloud Microservices RESTful

Posted on Sat, 18 Sep 2021 07:02:54 -0400 by scrupul0us