Overview of OpenFeign

Introduction to OpenFeign

Github address: github.com/spring-clou…

Official documentation: Spring Cloud

Feign is a declarative WebService client. Using Feign makes writing Web Service clients much easier. It is used by defining a service interface and then adding annotations to it.

Feign also supports pluggable encoders and decoders. Spring Cloud encapsulates Feign to support Spring MVC standard annotations and HttpMessageConverters. Feign can be used in combination with Eureka and the Ribbon to support load balancing.

2,

Feign is designed to make it easier to write Java Http clients.

When Ribbon+RestTemplate is used, the RestTemplate encapsulates HTTP requests and creates a set of template invocation methods. However, in real development, because service dependencies may be called in more than one place, often an interface may be called in more than one place, it is common to wrap some client classes for each microservice to wrap the invocation of these dependent services. So, Feign took this one step further and helped us define and implement the definition of the dependent service interface. Under the Feign implementation, ** we only need to create an interface and configure it with annotations (previously Dao interface with Mapper annotation, now it is a micro service interface with Feign annotation), ** can complete the interface binding to the service provider. Simplifies the development of automatically wrapped service invocation clients when using Spring Cloud Ribbon.

Feign integrates with the Ribbon

The Ribbon maintains the Payment service list and implements load balancing through polling. Unlike the Ribbon, Feign provides elegant and simple service invocation in a declarative way by defining the service binding interface.

4. Difference between Feign and OpenFeign

  • Feign is a lightweight RESTful HTTP service client in the Spring Cloud component. Feign has the Ribbon built in, which is used to load balance clients and invoke services in the service registry. Feign is used by using Feign’s annotations to define an interface that can be invoked to invoke the services of the service registry.

  • OpenFeign is a Spring Cloud annotation that supports SpringMVC on top of Feign, such as @requesMapping, etc. OpenFeign’s @FeignClient can parse the interface under SpringMVC’s @RequestMapping annotation and generate implementation classes through dynamic proxy, which can perform load balancing and call other services.

Ii. How to use OpenFeign

Create module cloud-consumer-feign-order80

Create the cloud-consumer-feign-order80 module with feign on the consumer side.


      
<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>cloud2021</artifactId>
        <groupId>com.atguigu</groupId>
        <version>1.0.0 - the SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.springcloud</groupId>
    <artifactId>cloud-consumer-feign-order80</artifactId>

    <dependencies>
        <! --openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <! --eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <! -- Introduced a generic API package that allows you to pay Entity using Payment -->
        <dependency>
            <groupId>com.atuguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <! --web-->
        <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>
        <! -- Basic General Configuration -->
        <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>
Copy the code

Yaml files.

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
Copy the code

The main startup class, annotated @enableFeignClients instead:

@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
    public static void main(String[] args) { SpringApplication.run(OrderFeignMain80.class,args); }}Copy the code

2. Business class creation

Service logic interface + @feignClient Configures to invoke the Provider service

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}

Copy the code

The controller layer

@RestController
@Slf4j
public class OrderFeignController {
    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        returnpaymentFeignService.getPaymentById(id); }}Copy the code

Start the test: localhost/consumer/payment/get/success.

3. OpenFeign timeout control

1, the timeout demo error situation

Service Providers 8001 and 8002 intentionally wrote suspension programs

8001 controller layer write timeout program

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout(a){
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return serverPort;
}
Copy the code

Service consumer 80 add timeout method PaymentFeignService

Add timeout logic to the PaymentFeignService interface.

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout(a);
}
Copy the code

Service consumer 80 adds the timeout method OrderFeignController

@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeout(a){
    // OpenFeign is the ribbon at the bottom, and consumers wait 1s by default
    return paymentFeignService.paymentFeignTimeout();
}
Copy the code

Start with this test: localhost: 8001 / payment/feign / / timeout, here is the access to their own path, 8001 spent a total of 3 s.

And test the path to the localhost/consumer/payment/feign / / timeout, an error:

By default, the Feign client only waits for 1s. If the server processes more than 1s, the Feign client directly reports an error. You can set the Feign client timeout control.

Cloud-consumer-feign-order80 YAML configuration:

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      
# Set the feign client timeout (OpenFeign supports the ribbon by default)
ribbon:
  # refers to the time it takes to establish a connection. It is applicable to the time it takes to establish a connection between two ends under normal network conditions
  ReadTimeout: 5000
  # refers to the time it takes to read the available resources from the server after the connection is established
  ConnectTimeout: 5000
Copy the code

Test again, no error, output 8001 or 8002. Note The client timeout is successfully modified.

OpenFeign’s logging enhancements

1. Log printing

Feign provides log printing, which can be configured to tune the severity level of the day to see the details of Http requests in Feign.

Basically, it monitors and outputs calls to the Feign interface

2. Log level

  • NONE: By default, no logs are displayed.
  • BASIC: only request method, URL, response status code and execution time are recorded;
  • HEADERS: Request and response HEADERS in addition to the information defined in BASIC;
  • FULL: In addition to the information defined in HEADERS, there is the body and metadata of the request and response.

3. Configure logs

Create the Config package and FeignConfig class.

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(a){
        returnLogger.Level.FULL; }}Copy the code

Yaml file configuration:

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

# Set the feign client timeout (OpenFeign supports the ribbon by default)
ribbon:
  # refers to the time it takes to establish a connection. It is applicable to the time it takes to establish a connection between two ends under normal network conditions
  ReadTimeout: 5000
  # refers to the time it takes to read the available resources from the server after the connection is established
  ConnectTimeout: 5000

logging:
  level:
    # feign Logging monitors which interface at what level
    com.atguigu.springcloud.service.PaymentFeignService: debug
Copy the code

Start the test and find that a detailed log is printed.