Microservice invocation component Feign

How to implement interface call in Java project

1>Httpclient
Httpclient is a sub project under Apache Jakarta Common, which is used to provide an efficient, up-to-date and feature rich client programming toolkit supporting HTTP protocol, and it supports the latest version and recommendations of HTTP protocol. Compared with the URLConnection of the traditional JDK, httpclient improves the ease of use and flexibility, makes it easy for the client to send HTTP requests, and improves the efficiency of development.
2>Okhttp
An open source project for processing network requests is the most popular lightweight framework at Andrews. It is contributed by Square to replace HttpUrlConnection and Apache HttpClient. OkHttp has a concise API, efficient performance, and supports a variety of protocols (HTTP/2 and SPDY).
3>HttpURLConnection
HttpURLConnection is a standard class of Java. It inherits from URLConnection and can be used to send GET requests, POST requests and HttpURLConnection to specified websites. The use of HttpURLConnection is complex and not as easy as HttpClient.
4>RestTemplate WebClient
RestTemplate is a client provided by Spring to access Rest services. RestTemplate provides a variety of convenient methods to access remote HTTP services, which can greatly improve the writing efficiency of the client.

The above describes the most common methods of calling interfaces. The method we will introduce below is simpler and more convenient than the above. It is Feign.

What is Feign

Feign is a declarative and templated HTTP client developed by Netflix. It is inspired by Retrofit, JAXRS-2.0 and WebSocket. Feign can help us call HTTP API more conveniently and gracefully.
Feign supports a variety of annotations, such as Fegin's own annotations or JAX-RS annotations.

Spring Cloud openfeign enhances Feign to support Spring MVC annotations. In addition, it integrates Ribbon and Nacos, making Feign more convenient to use.

Advantages: Feign can achieve the same experience as calling a local method when using HTTP to request a remote service. Developers are completely unaware that this is a remote method, let alone an HTTP request. Like Dubbo, the consumer directly calls the interface method to call the provider without parsing the returned data through the conventional Http Client construction request. It solves the problem that developers call the remote interface like calling the local method, without paying attention to the details of remote interaction, let alone the development of distributed environment.

Spring Cloud Alibaba quickly integrates OpenFeign

1. Introduce dependency

<!--1.add to openfeign rely on-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. Write calling interface + @ FeignClient annotation

/**
 * 2.Add feign interfaces and methods
 * name  Specify the service name corresponding to calling the rest interface
 * path  Specifies the StockController where the rest interface is called@
 */
@FeignClient(name = "stock-service", path = "/stock")
public interface StockFeignService {

    /**
     * Declare the method corresponding to the rest interface to be called
     * @return
     */
    @RequestMapping("/reduct")
    String reduct();

}

3. The caller adds the @ EnableFeignClients annotation on the startup class. This annotation is not required for higher versions.

@SpringBootApplication
@EnableFeignClients
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

}

4. Initiate the call and call the remote service like calling the local method

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @Autowired
    StockFeignService stockFeignService;

    @RequestMapping("/add")
    public String add(){
        log.info("Order successfully!");
        String result = stockFeignService.reduct();
        return "Hello Feign !" + result;
    }
}

Custom configuration and use of Spring Cloud Alibaba

Feign provides many extension mechanisms so that users can use them more flexibly.

1. Log configuration
Sometimes when we encounter bugs, such as interface call failure, parameters not received, or want to see the call performance, we need to configure Feign's log to let Feign output the request information.

1> Define a configuration class and specify the log level

/**
 * Note: if the @ Configuration annotation is configured here, it will take effect globally. If you want to specify the corresponding microservice to take effect, it cannot be configured
 */
@Configuration
public class FeignConfig {

    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

From the source code, you can see that there are four log levels, namely:
(1) NONE [best performance, suitable for production]: no log is recorded (default).
(2) BASIC [applicable to production environment tracking problem]: only record the request method, URL, response status code and execution time.
(3) HEADERS: record the header s of requests and responses based on the BASIC level.
(4) FULL [more applicable to development and test environment positioning]: record the header, body and metadata of requests and responses.

2> Only by executing the log level of the Client in the yml configuration file can the log be output normally. The format is "logging.level.feign interface package path = debug"

#The default log level of Springboot is info, and the debug log level of feign will not be entered
logging:
  level:
    com.mu.order.feign: debug

3> Local configuration to make the invoked microservice effective, and specify the configuration class used in the @ FeignClient annotation

@FeignClient(name = "product-service", path = "/product", configuration = FeignConfig.class)
public interface ProductFeignService {

    @RequestMapping("/{id}")
    String get(@PathVariable("id") Integer id);
}

4> Local configuration can be configured in yml

# feign log local configuration
feign:
  client:
    config:
      stock-service:
        loggerLevel: BASIC


2. Contract allocation
Spring Cloud extends Feign and uses spring MVC annotations to complete Feign's functions. The native Feign does not support spring MVC annotation. If you want to use the native annotation method to define the client in Spring Cloud, you can change the configuration through the configuration contract. Spring MVC contract is the default in Spring Cloud.

The early version of Spring Cloud 1 used the native Fegin, which was replaced with Openfeign with the shutdown of Netflix.

1> Modify the contract configuration to support Feign's native annotations

/**
* Modify the contract configuration to support Feign's native annotations
* @return
*/
@Bean
public Contract feignContract(){
	return new Contract.Default();
}

Note: after modifying the contract configuration, ProductFeignService no longer supports the annotation of springmvc, but needs to use the native annotation of Fegin

2> Configuring Feign native annotations in ProductFeignService

@FeignClient(name = "product-service", path = "/product")
public interface ProductFeignService {

    /*@RequestMapping("/{id}")
    String get(@PathVariable("id") Integer id);*/

    @RequestLine("GET /{id}")
    String get(@Param("id") Integer id);
}

3> Additionally, you can also configure contracts through yml

# feign log local configuration
feign:
  client:
    config:
      product-service:
        loggerLevel: BASIC
        contract: feign.Contract.Default # Contract set as default (revert to original annotation)

3. Timeout configuration
The connection timeout and read timeout can be configured through Options. The first parameter of Options is the connection timeout (ms), and the default value is 2s; The second is the request processing timeout (ms). The default value is 5s.

Global configuration:

@Configuration
public class FeignConfig{
	@Bean
	public Request.Options options(){
		return new Request.Options(5000,10000);
	}
}

Configuration in yml:

# feign log local configuration
feign:
  client:
    config:
      product-service:
        loggerLevel: BASIC
        contract: feign.Contract.Default # Contract set as default (revert to original annotation)
        # Connection timeout, 2s by default
        connectTimeout: 5000
        # Request processing timeout, default 5s
        readTimeout: 3000

Supplementary note: the bottom layer of Feign uses Ribbon, but the timeout time is subject to Feign configuration.

Test timeout:

4. The user-defined interceptor implements authentication logic

public class CustomFeignInterceptor implements RequestInterceptor {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public void apply(RequestTemplate requestTemplate) {
        //TODO
        requestTemplate.header("xxx", "xxx");
        requestTemplate.query("id", "111");
        requestTemplate.uri("/9");

        logger.info("feign Interceptor!");
    }
}

Global configuration:

 /**
 * custom interceptor 
 * @return
 */
public CustomFeignInterceptor customFeignInterceptor(){
    return new CustomFeignInterceptor();
}

You can configure in yml:

# feign log local configuration
feign:
  client:
    config:
      product-service:
        loggerLevel: BASIC
        contract: feign.Contract.Default # Contract set as default (revert to original annotation)
        # Connection timeout, 2s by default
        connectTimeout: 5000
        # Request processing timeout, default 5s
        readTimeout: 10000
        requestInterceptors:
          - com.mu.order.interceptor.feign.CustomFeignInterceptor

Test:

Tags: Java Spring Cloud Microservices Cloud Native

Posted on Sun, 21 Nov 2021 15:13:37 -0500 by margarette_a