OpenFeign -- declarative call to remote method -- spring cloud

Posted by dhaselho on Tue, 30 Nov 2021 12:33:43 +0100

6.OpenFeign service interface call

6.1. General

6.1.1. What is openfeign

Feign is a declarative web service client, which makes it very easy to write a web service client. You just need to create an interface and add annotations on the interface
Spring cloud encapsulates feign to support spring MVC standard annotations and HttpMessageConverters. Feign can be used in combination with Eureka and Ribbon to support load balancing.
https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign
https://github.com/spring-cloud/spring-cloud-openfeign

6.1.2. What can I do

What can Feign do?
Feign aims to make it easier to write Java Http clients using.
When Ribbon+RestTemplate is used earlier, a set of templated calling methods are formed by encapsulating Http requests with RestTemplate.

However, in the actual development, because there may be more than one call to the service dependency, and often an interface will be called in multiple places, some client classes are usually encapsulated for each micro service to wrap these dependent service endpoint calls. Therefore, Feign made further encapsulation on this basis to help us define and implement the definition of dependent service interfaces.
Under the implementation of Feign, we only need to create an interface and configure it by annotation (previously, the DAO interface was marked with Mapper annotation, but now it is a micro service interface marked with Feign annotation), so as to complete the interface binding to the service provider, which simplifies the development of automatically encapsulating the service call client when using the Spring Cloud Ribbon.

Feign integrates Ribbon
The Ribbon is used to maintain the service list information of Payment, and the load balancing of the client is realized through polling. Unlike Ribbon, Feign only needs to define the service binding interface, and implements the service invocation gracefully and simply in a declarative way.
The difference between Feign and OpenFeign

6.2. Steps for using openfeign

6.2.1. Interface + annotation

Microservice calling interface + @ FeignClient

6.2.2. Create a new Module: cloud consumer feign order80

6.2.3.POM

Note: openFeign also comes with its own bibbon

<?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-parent</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-consumer-feign-order80</artifactId>

    <dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.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> 

6.2.4.YML

server:
  port: 80
spring:
  application:
    name: cloud-consumer-feign-order80
eureka:
  client:
register-with-eureka: true
fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

6.2.5. Main startup

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

6.2.6. Business

1. Business logic interface + @ FeignClient configuration calls the provider service

2. Create a PaymentFeignService interface and add the annotation @ FeignClient

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import feign.Param;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

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

3. Control layer Controller

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentFeignService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;  //Call remote micro service interface

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

6.2.7. Test

1. Start Eureka7001 first
2. Restart two microservices 8001 / 8002
3. Start OpenFeign microservice: cloud consumer feign order80
4.http://localhost/consumer/payment/get/31
5.Feign has its own load balancing configuration item

6.2.8. Summary

6.3.OpenFeign timeout control

6.3.1. Timeout setting: deliberately set timeout to demonstrate error

1. Service provider 8001 intentionally writes suspension procedures

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout(){
    try { TimeUnit.SECONDS.sleep(3); }catch (Exception e) {e.printStackTrace();} //Unit second
    return serverPort;
}

2. The service consumer 80 adds the timeout method PaymentFeignService

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout();

3. The service consumer 80 adds the timeout method OrderFeignController

@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeout(){
   return paymentFeignService.paymentFeignTimeout();
}

4. Test
http://localhost/consumer/payment/feign/timeout
On the error page, OpenFeign will wait for one second by default, and an error will be reported after it is exceeded

6.3.2. What is it

By default, the Feign client only waits for one second, but the server processing takes more than one second, so the Feign client doesn't want to wait and directly reports an error.
To avoid this situation, sometimes we need to set the timeout control of Feign client, that is, the timeout of Ribbon, because Feign integrates Ribbon for load balancing.

6.3.3. The timeout control of OpenFeign client needs to be enabled in YML

Feign set timeout
The Feign call interface is divided into two layers: Ribbon call and hystrix call, so the combination of ribbon timeout and hystrix timeout is Feign timeout

#Set Feign client timeout (openfeign supports ribbon by default)
ribbon:
  ReadTimeout:  3000
  ConnectTimeout: 3000

Topics: Java Spring Cloud feign