【SpringCloud】SpringCloud Feign详解

foreword

Microservices are decomposed into multiple different services, so how to call between multiple services?
The latest Spring Cloud interview questions
Spring Cloud Nacos Detailed Registration Center
Spring Cloud Nacos Detailed Configuration Center
Spring Cloud Nacos Detailed Cluster Configuration
Spring Cloud Eureka Detailed
Spring Cloud Ribbon Detailed
Spring Cloud Gateway Detailed
Spring Cloud Hystrix Detailed

SpringCloud Feign remote service call

1. Remote call logic diagram

Now there are two services, order service (service consumer) and user service (service provider), which correspond to different databases.
Note: Because remote calls are made by service consumers to call service providers, configuration and business writing are all in service consumers.
insert image description here

2. The yml configuration and access path of the two services

用两个不同的数据库,模拟部署在两台服务器的数据库

订单yml配置   访问路径:@GetMapping("order/{
    
    orderId}")
server:
  port: 8082
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: orderservice //订单服务的名称


用户yml配置  访问路径:@GetMapping("user/{
    
    id}")
server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: userservice //用户服务的名称

3. Use RestTemplate to call remotely

1. Inject RestTemplate

	/**
	 * 因为启动类本身也是一个配置了,所以我们在启动类进行注入,你自己自定义配置类注入也行
     * 创建RestTemplate并注入Spring容器
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    
    
        return new RestTemplate();
    }

2. Write a remote call


	@Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
    
    
        // 根据订单id查询订单
        Order order = orderMapper.findById(orderId);
        // 利用RestTemplate发起http请求,根据用户id查询用户
        // url路径  http://服务名称(上面配置了)/请求路径/参数
        String url = "http://localhost:8081/user/" + order.getUserId();
        // 发送http请求,实现远程调用,现在是get请求类型
        User user = restTemplate.getForObject(url, User.class);
        // 封装user到Order
        order.setUser(user);
        // 返回值
        return order;
    }

3. Disadvantages of RestTemplate

  • URLs with complex parameters are difficult to maintain.
  • It does not conform to the format of normal interface calls.

4. Build Feign

1. Introduce dependencies

		<!--feign客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2. Use annotations in the startup class to enable the Feign function

@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
    
    
}

3. Write remote calls

//服务名称
@FeignClient(value = "userservice")
public interface UserClient {
    
    

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
    
}

4. Call interface


    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
    
    
        // 根据订单id查询订单
        Order order = orderMapper.findById(orderId);
        // 用Feign远程调用
        User user = userClient.findById(order.getUserId());
        // 封装user到Order
        order.setUser(user);
        // 返回
        return order;
    }

5. Feign also integrates Ribbon, so we don't have to consider load balancing

insert image description here

5. Customize Feign configuration

type effect illustrate
feign.Logger.Level Modify log level Four different levels: NONE (no log), BASIC (start and end time of the request), HEADERS (record the request header request body), FULL (request and response information)
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 SpringMVC
feign. Retryer Failure retry mechanism The retry mechanism for request failure, the default is no, but Ribbon's retry will be used

Generally, we customize the configuration of the log

6. Feign configuration log

1. Configuration file configuration log

//全局配置
feign:
	client:
		config:
			default://default全局配置,远程调用的服务的接口也会打印。
				loggerLevel:FULL //日志级别

//局部配置
feign:
	client:
		config:
			orderservice://只打印服务名为orderservice的日志。
				loggerLevel:FULL //日志级别

2. Code configuration log

//第一步:注入对象
public class DefaultFeignConfiguration {
    
    
    @Bean
    public Logger.Level logLevel(){
    
    
    	//日志级别
        return Logger.Level.BASIC;
    }
}
//第二步:注解配置

//全局配置
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)

//局部配置
@FeignClient(value = "userservice",confiquration = FeignClientConfiguration.class)

Seven. Feign tuning

Feign underlying client implementation:

  • URLConnection: The default implementation does not support connection pooling.
  • Apache HttpClient: supports connection pooling.
  • OKHttp: supports connection pooling.

1. Use the connection pool instead of the default URL Connection (supported by HttpClient)

①The pom file introduces dependencies

	    <!--引入HttpClient依赖-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

②yml file for configuration

feign:
  httpclient:
    enabled: true # 支持HttpClient的开关
    max-connections: 100 # 最大连接数
    max-connections-per-route: 25 # 单个路径的最大连接数

2. The log level is preferably basic or none

8. Pull away from Feign

If A, B, and C services all call D services, do we need to use Feign to call D in A, B, and C? If we write it, it will cause a lot of code redundancy, so we need to extract Feign and put it in Inside a public service. We create a new Feign-api service, and then whoever uses it will introduce it in the pom file.

Note: It is necessary to write the called interface (plus @FeignClient(vaule=服务名)annotation) and entity class in the public service.

Feign-api structure directory
insert image description here

		<!--谁用谁引入,引入feign的统一api-->
        <dependency>
            <groupId>cn.xinxin.demo</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0</version>
        </dependency>

But doing so will cause SpringBootApplication to not be able to define the FeignClient object when scanning the package, so how to solve it?

solve

方式一:指定FeignClient所在包
@EnableFeignClients(basePackages = "cn.xinxin.feign.clients")

方式二:指定FeignClient字节码
EnableFeignClients(clients = {
    
    UserClient.class})

Feign's pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-demo</artifactId>
        <groupId>cn.xinxin.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feign-api</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
    	<!--feign客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
</project>

Example: Order service calls user service remotely
insert image description here

Guess you like

Origin blog.csdn.net/twotwo22222/article/details/129319448