Microservice study notes--(Feign)

http client Feign

  • Feign replaces RestTemplate
  • custom configuration
  • Feign usage optimization
  • Best Practices

Problems with calling RestTemplate

The code that used to initiate remote calls using RestTemplate:

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

There are following problems:

  • Poor code readability and inconsistent programming experience
  • URLs with complex parameters are difficult to maintain

Feign's introduction

Feign is a declarative http client, official address: http://github.com/OpenFeign/feign
Its role is to help us send http requests elegantly and solve the problems mentioned above.


Define and use Feign client

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. Enable the function of Feign in the Tainan Jia annotation of the order-service startup class

@EnableFeignClients
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
    
    
	public static void main(String[] args) {
    
    
		SpringApplication.run(OrderApplication.class, args);
	}
}

The steps to use Feign are as follows:

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. Use Feign client instead of RestTemplate

@Autowired
private UserClient userClient;

public Order queryOrderById(Long orderId) {
    
    
	// 1.查询订单
	Order order = orderMapper.findByid(orderId);
	// 2.利用Feign发起http请求,查询用户
	User user = userClient.findById(order.getUserId());
	// 3.封装user到Order
	order.setUser(user);
	// 4.返回
	return order;
}

summary:

Steps to use Feign:

  • Introduce dependencies
  • Add @EnableFeignClients annotation
  • Write the FeignClient interface
  • Use methods defined in FeignClient instead of RestTemplate

Feign - custom configuration

Customize the configuration of Feign

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

type effect illustrate
feign.Logger.Level Modify log level Contains four different levels: NONE, BASIC, HEADERS, FULL
feign.codec.Decoder Parser for the response result Parsing the results of http remote calls, such as parsing json strings into java objects
feign.codec.Encoder request parameter encoding Encode request parameters for sending via http requests
feign.Contract Supported Annotation Formats The default is the annotation of the MVC of S weekdays
feign.Retryer Failure retry mechanism The retry mechanism for request failure, the default is no, but Ribbon's retry will be used

Generally, what we need to configure is the log level.

There are two ways to configure Feign logs:

Method 1: configuration file method

  • Take effect globally:
feign:
  client:
    config:
      default: #这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL # 日志级别
  • partial effect
feign:
  client:
    config:
      userservice: #这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL # 日志级别

The second method of configuring Feign logs: java code method, you need to declare a Bean first:

public class FeignClientConfiguration {
    
    
	@Bean
	public Logger.Level feignLogLevel() {
    
    
		return Logger.Level.BASIC;
	}
}
  • If it is a global configuration, put it in the @EnableFeignClients annotation:
@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)
  • If it is a partial configuration, put it in the @FeignClient annotation:
@FeignClients(value="userservice", configuration = FeignClientConfiguration.class)

summary:

Feign's log configuration:

1. The first method is the configuration file, feign.client.config.xxx.loggerLevel

  • If xxx is default, it means global
  • If xxx is the service name, such as userservice, it represents the service

2. The second method is to configure the Logger.level Bean in java code

  • If declared in the @EnableFeignClients annotation, it represents the global
  • If declared in the @FeignClient annotation, it represents a service

Feign-performance optimization

Feign performance optimization

The underlying client implementation of Feign:

  • URLConnection: default implementation, does not support connection pooling
  • Apache HttpClient: supports connection pooling
  • 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 performance optimization - connection pool configuration

Feign adds HttpClient support:
import dependencies:

<!--httpClient的依赖-->
<dependency>
	<groupId>io.github.openfeign</groupId>
	<artifactId>feign-httpclient</artifactId>
</dependency>

Configure the connection pool:

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对httpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径最大的连接数

summary:

Feign's optimization:

1. Try to use basic as the log level
2. Use HttpClient or OKHttp instead of URLConnection

  • Introduce feign-httpClient dependency
  • The configuration file enables the httpClient function and sets the connection pool parameters

Feign - Best Practice Analysis

Best Practices for Feign

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

  • Services Tightly Coupled
  • Mappings in parent interface parameter lists are not inherited
public interface UserAPI {
    
    
	@GetMapping("/user/{id}")
	User findById(@PathVariable("id") Long id);
}
@FeignClient(value = "userservice")
public interface UserClient extends UserAPI{
    
    }
@RestController
public class UserController implements UserAPI{
    
    
	public User findById(@PathVariable("id") Long id){
    
    
		// ...实现业务
	}
}

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

summary:

Best practices for Feign:

  1. Let controller and FeignClient inherit the same interface
  2. Define the default configuration of FeignClient, POJO, and Feign into one project for all consumers to use

Feign - Implementing Feign best practices

Extract FeignClient

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

1. First create a module named feign-api, and then import feign's starter dependency
2. Copy the UserClient, User, and Default FeignConfiguration written in order-service to the feign-api project
3. Introduce feign in order-service -api depends on
4. Modify all the import parts related to the above three components in order-service, and change it to import the package in feign-api
5. Restart the test

When the defined FeignClient is not within the scanning range of SpringBootApplication, these FeignClient cannot be used. There are two ways to solve it:

Method 1: Specify the package where FeignClient is located

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

Method 2: Specify FeignClient bytecode

@EnableFeignClients(clients= {
    
    UserClient.class})

summary:

There are two ways to import FeignClient of different packages:

  • Add basePackages in the @EnableFeignClients annotation to specify the package where FeignClient is located
  • Add clients to the @EnableFeignClients annotation to specify the bytecode of the specific FeignClient

Guess you like

Origin blog.csdn.net/weixin_42594143/article/details/130579454