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})