Teach you how to build a SpringCloud project (9) Integrate OpenFeign service interface calls

What are microservices? A series will be seen at a glance!

1. Teach you how to build a SpringCloud project (1) Detailed explanation with pictures and texts, fool-like operation

2. Teach you how to build a SpringCloud project (2) Producers and consumers

3. Teach you how to build a SpringCloud project (3) Integrate the Eureka service registration center

4. Teach you how to build the SpringCloud project (4) Eureka cluster version construction

5. Teach you how to build the SpringCloud project (5) Build the producer cluster version

6. Teach you how to build a SpringCloud project (6) Eureka realizes service discovery

7. Teach you how to build a SpringCloud project (7) Integrate the Consul service registration center

8. Teach you how to build a SpringCloud project (8) Integrated Ribbon load balancer

9. Teach you how to build a SpringCloud project (9) Integrate OpenFeign service interface calls

10. Teach you how to build a SpringCloud project (10) Integrate Hystrix service downgrade

11. Teach you to build a SpringCloud project (11) Integrating Hystrix's service fuse

12. Teach you how to build a SpringCloud project (12) Integrate Hystrix's graphical Dashboard real-time monitoring

13. Teach you how to build a SpringCloud project (13) Integrate a new generation of Gateway

14. Teach you how to build a SpringCloud project (14) Integrated Config Distributed Configuration Center

15. Teach you how to build a SpringCloud project (15) Integrated Bus message bus

16. Teach you how to build a SpringCloud project (16) Integrated Stream message driver

17. Teach you how to build a SpringCloud project (17) Integrating Sleuth distributed link tracking

Continue to update, welcome to like and follow!

1. Introduction to OpenFeign

What is Feign?

    Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。它的使用方法是定义一个服务接口然后在上面添加注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用支持负载均衡。 

What can Feign do?

    Feign旨在使编写Java Http客户端变得更容易。前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发过程中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它,(以前是Dao接口上面标准Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可)即可完成对服务提供方的接口绑定,简化了Spring  Cloud Ribbon时,自动封装服务调用客户端的开发量。

    **Feign集成了Ribbon,利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign值需要定义服务绑定接口且一声明式的方法,优雅而简单的实现了服务调用。**

The difference between Feign and OpenFeign

insert image description here

2. Openfeign implements load balancing

Create a new module named cloud-consumer-feign-order and modify the pom.xml 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>mcroservice</artifactId>
        <groupId>com.study.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
 
    <artifactId>cloud-consumer-feign-order</artifactId>
    <description>订单消费者之feign</description>
 
    <dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--hystrix-->
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.study.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
</project>

Create a new application.yml configuration file

server:
  port: 80
#eureka集群
eureka:
  client:
    register-with-eureka: false
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

New main startup class

package com.buba.springcloud;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
 
@SpringBootApplication
@EnableFeignClients//激活Feign的注解  需要加到主启动类上
public class OrderFeignMain {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderFeignMain.class,args);
    }
}

To create a new business class is to copy the business interface of our producer's service and use it directly

package com.buba.springcloud.service;
 
import com.buba.springcloud.pojo.CommonResult;
 
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
 
 
@ComponentScan
@FeignClient(value ="mcroservice-payment")//使用Feign
public interface PaymentService {
    
    
    @GetMapping("/payment/get/{id}")
    public CommonResult queryById(@PathVariable("id") Long id);
  
}

Create a new control layer Controller

package com.buba.springcloud.controller;
 
 
import com.buba.springcloud.pojo.CommonResult;
import com.buba.springcloud.pojo.Payment;
import com.buba.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@Slf4j
public class OrderFeignController {
    
    
    @Autowired
    private PaymentService paymentService;
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
    
    
        CommonResult result = paymentService.queryById(id);
        return result;
    }
   
}

Then start eureka7001 and 7002 now, and then start the server service 8001 and 8002, first test yourself to see if the startup is successful. Start the producer service 80 configured with OpenFeign, access the path http://localhost/consumer/payment/get/1, and see if there is a function of assignment balance.
insert image description here

To sum up, Openfeign is the microservice call interface + @FeignClient annotation, as shown below:
insert image description here
insert image description here

3. Openfeign implements timeout control

Since our services are divided into producers and consumers, when our consumer service calls the producer service, it takes a long time to respond, and the connection timeout will occur. If there is no response for a long time, it will cause extremely poor results to the user. Experience, at this time we can set the timeout implementation, for example, when our consumer service calls the producer service, we can set that if there is no response for more than 2 seconds when accessing the producer service, a prompt will be given to the user, and the connection timed out, please Visit later. Both the producer service and the consumer service need to set regulations.

Then the following code demonstrates the timeout setting, which makes it easier to understand and learn intuitively. We write an interface for the service whose producer port is 8001, let the program pause for 3 seconds, and deliberately set the timeout to demonstrate the error situation, as shown in the following figure:

//模拟业务接口延时3秒
@GetMapping("/payment/feign/timeout")
public String PaymentFeignTimeOut() throws InterruptedException {
    
    
     TimeUnit.SECONDS.sleep(3);
     return serverPort;
}

Add a timeout interface in the consumer service business layer, as shown in the figure below:

package com.buba.springcloud.service;
 
import com.buba.springcloud.pojo.CommonResult;
 
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
 
 
@ComponentScan
@FeignClient(value ="mcroservice-payment")//使用Feign,使用哪个微服务
public interface PaymentService {
    
    
    //调用生产者微服务名称为mcroservice-payment下边的接口
    @GetMapping("/payment/get/{id}")
    public CommonResult queryById(@PathVariable("id") Long id);
    //调用生产者微服务名称为mcroservice-payment下边的模拟超时的接口
    @GetMapping("/payment/feign/timeout")
    public String PaymentFeignTimeOut() throws InterruptedException;
 
}

Add a timeout interface at the consumer service control layer, as shown in the figure below:

package com.buba.springcloud.controller;
 
 
import com.buba.springcloud.pojo.CommonResult;
import com.buba.springcloud.pojo.Payment;
import com.buba.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@Slf4j
public class OrderFeignController {
    
    
    @Autowired
    private PaymentService paymentService;
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
    
    
        CommonResult result = paymentService.queryById(id);
        return result;
    }
    @GetMapping("/consumer/feign/timeout")
    public String PaymentFeignTimeOut() throws InterruptedException{
    
    
        return paymentService.PaymentFeignTimeOut();
    }
}

Let's first self-test the microservice and access interface of the producer whose port is 8001 http://localhost:8001/payment/feign/timeout, as shown in the figure below:
insert image description here

After passing the self-test to access the consumer's service, the interface is http://localhost/consumer/feign/timeout, and the following error interface will appear, prompting us that the interface access timed out.
insert image description here

The reason is that Openfeign waits for 1 second by default, and will report an error after it exceeds. However, our producer service does need to process complex business, and the processing time will exceed 1 second, so we need to modify the default waiting time of Openfeign. It needs to be set in the yml file of the consumer service. Because Feign integrates the Ribbon, you need to set the Ribbon related. As shown below:

server:
  port: 80
eureka:
  client:
    register-with-eureka: false
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
 
# 设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  # 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间,设置等待5000为5秒时间
  ReadTimeout: 5000
  # 指的是建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

We restart the consumer service and visit ttp://localhost/consumer/feign/timeout again, and the following success interface will appear:

insert image description here

4. Openfeign implements log printing

Openfeign provides a log printing function. For example, when our consumer service calls the producer's service and calls the interface, we may need more detailed information, such as information header, status code, time, interface, and so on. You can use the Openfeign log printing function, and we can adjust the log level through configuration to understand the details of the Http request in Feign. That is to monitor and output the call status of the Feign interface.

There are four types of Loggers:

NONE: By default, no logs are displayed.

BASIC: Only record the request method, URL, response status and execution time.

HEADERS: In addition to the information defined in BASIC, there are information about requests and responses.

FULL: In addition to the information defined in BASIC, there are request and response body and metadata.

Set the logging level by registering the bean!

Start configuring the log bean, we create a new configuration file FeignConfig, remember to add @Configuration

package com.buba.springcloud.config;
 
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class FeignConfig
{
    
    
    /**
     * feignClient配置日志级别
     *
     * @return
     */
    @Bean
    public Logger.Level feignLoggerLevel() {
    
    
        // 请求和响应的头信息,请求和响应的正文及元数据
        return Logger.Level.FULL;
    }
}

In the yml file, you need to open the Feign client of the log, and write the fully qualified class name of the PaymentService business class

logging:
  level:
      # feign日志以什么级别监控哪个接口
    com.buba.springcloud.service.PaymentService: debug

Restart the consumer service, access the interface, and look at the log information printed on the console.
insert image description here

OpenFeign has learned here, it is so easy!

insert image description here

In the next article, let's continue Hystrix and continue to cheer duck!

Guess you like

Origin blog.csdn.net/weixin_39570655/article/details/131810328