Step by step screenshot of Feign learning notes of spring cloud service registration discovery (service governance) (with source code project written during learning)

SpringCloud

The project source code written during the learning of the whole spring cloud: git@gitee.com:HumorChen/spring-cloud-parent.git
The last blog was: eureka (service governance) Step by step screenshot of Eureka learning notes of spring cloud service registration discovery (service governance) (with the source code project written during learning)
Download the git project above before reading this blog.

Getting to know Spring Cloud

What is micro service

  • The word "Microservices" comes from Martin Fowler's blog post called Microservices, which can be found on his official blog
    http://martinfowler.com/articles/microservices.html
  • Microservice is a design style of system architecture. Its main purpose is to split an originally independent system into multiple small services. These small services run in their own independent processes. Services generally communicate and cooperate through HTTP RESTfuLAPI.
  • Each small service is built around one or more business functions with high coupling in the system, and each service maintains white data storage, business development automation test cases and independent deployment mechanism.

Introduction to spring cloud

  • spring cloud is an ordered collection of a series of frameworks

  • spring cloud does not manufacture wheels repeatedly. It just combines the more mature and practical frameworks developed by various companies

  • Repackaging in Spring Boot style shields the complex configuration and implementation principles, and finally leaves a set of simple, easy to understand, easy to deploy and easy to maintain distributed system development kit for developers

  • Taking advantage of the development convenience of Spring Boot, it cleverly simplifies the development of distributed system infrastructure, such as service registration and discovery, configuration center, message bus, load balancing, circuit breaker, data monitoring, etc., which can be started and deployed with one click with the development style of Spring Boot.

  • The naming method of Spring Cloud version adopts the name of London underground station, and corresponds to the version time order according to the alphabet. For example, the earliest Release version is Angel, the second Release version is Brixton, and then Camden, Dalton, Edgware, Finchley,Greenwich and Hoxton

  • Correspondence between spring cloud version and springboot version

Spring Cloud vs. Dubbo

  • Both Spring Cloud and Dubbo are effective tools for implementing microservices.
  • Dubbo only implements service governance, while the Spring Cloud subproject covers many components under the micro service architecture.
  • Dubbo uses RPC communication protocol and Spring Cloud uses RESTful to complete communication. Dubbo is slightly more efficient than Spring Cloud.

Summary

  • Microservice is to split each module of the project into an architecture design style that can be run, deployed and tested independently.
  • Spring company integrates the components commonly used in microservice architecture in other companies, and uses SpringBoot to simplify its development and configuration. Called Spring Cloud
  • Both Spring Cloud and Dubbo are effective tools for implementing microservices. Dubbo has better performance and Spring Cloud is more comprehensive.

Feign declarative service invocation

Feign introduction

  • Feign is a declarative REST client. It uses interface based annotation to facilitate client configuration.
  • Feign was initially provided by Netflix, but does not support spring MVC annotations. Later, it was encapsulated by spring cloud and supports spring MVC annotations, making it easier for users to accept.

Feign usage steps

  1. Introduce open feign on the consumer side
  2. Write Feign call interface by dependency
  3. Add the @ EnableFeignClients annotation in the startup class to enable the Feign function
  4. Test call
  • Start a previous Eureka server, port 8761.

  • Create two modules, one is feign consumer and the other is feign provider. Copy the previous consumer and provider codes respectively. To modify the configuration, delete the 8762 eureka server in server rul

  • Start provider

  • Introducing the openfeign dependency in the consumer project

    <!-- feign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  • Annotate the consumer startup class with @ EnableFeignClients

    package com.fpa.consumer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    @SpringBootApplication
    @EnableEurekaClient
    @EnableDiscoveryClient
    @EnableFeignClients
    public class ConsumerApp {
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApp.class,args);
        }
    }
    
    
  • Create an interface to declare the interface to call

    @FeignClient(value = "provider app") this value is the name of the called service application passed

    The interface defined below is actually similar to the interface defined by the service provider. Only the getmapping parameter complements the uri prefix of / goods

    @GetMapping("/goods/{id}")
    public Goods findOne(@PathVariable("id") int id);
    
    //Service provider original
    @GetMapping("/{id}")
    public Goods findOne(@PathVariable("id") int id){
        return goodsService.findOne(id);
    }
    

    Complete code

    package com.fpa.consumer.interfaces;
    
    import com.fpa.consumer.bean.Goods;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    @FeignClient(value = "provider-app")
    public interface GoodsFeignClient {
    
        @GetMapping("/goods/{id}")
        public Goods findOne(@PathVariable("id") int id);
    
    }
    
  • Interface provided by consumer before modification

package com.fpa.consumer.controller;

import com.fpa.consumer.bean.Goods;
import com.fpa.consumer.interfaces.GoodsFeignClient;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/goods")
public class OrderController {

    /**
     * Inject the goods feign client interface we just wrote (it doesn't matter if idea is popular)
     */
    @Autowired
    private GoodsFeignClient goodsFeignClient;

    @GetMapping("/findGoodsById/{id}")
    public Goods findOne(@PathVariable("id") int id) {
        Goods goods = goodsFeignClient.findOne(id);
        return goods;

    }
}

  • Start the consumer and use postman to test the interface successfully

Feign timeout configuration

Feign bottom layer relies on ribbon to realize load balancing and remote invocation. Ribbon defaults to 1 second timeout

  • Add sleep to the provider interface, sleep for two seconds, and then return
package com.fpa.provider.controller;

import com.fpa.provider.bean.Goods;
import com.fpa.provider.service.GoodsService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    private GoodsService goodsService;

    @GetMapping("/{id}")
    public Goods findOne(@PathVariable("id") int id){
        try {
            Thread.sleep(2000);
        }catch (Exception e){}
        return goodsService.findOne(id);
    }
}

  • When the interface is called again, an error is reported from the consumer, and the reading timeout occurs

    java.net.SocketTimeoutException: Read timed out
    

  • Go to the application of the consumer project to uniformly configure the ribbon timeout

    spring:
      profiles:
        active: dev
      application:
        name: consumer-app
    
    #Set the timeout for the Ribbon
    ribbon:
      connectTimeout: 1000 #The connection timeout is 1s by default
      ReadTimeout: 3000 #The timeout of logical processing is 1s by default
    
  • Restart the consumer and test the interface with postman. After waiting for 2 seconds, the result is returned

Feign logging

  • Feign can only record debug level log information.

    logging:
      level:
        com.fpa: debug
    
  • Define Feign log level Bean

    @Bean
    Logger.Level feignLoggerLevel() {
    	return Logger.Level.FULL;
    }
    
  • Enable this Bean:

    @Feignclient(configuration = xxxConfig.class)
    
  • Modify the consumer's configuration file application yml

spring:
  profiles:
    active: dev
  application:
    name: consumer-app

#Set the timeout for the Ribbon
ribbon:
  connectTimeout: 1000 #The connection timeout is 1s by default
  ReadTimeout: 3000 #The timeout of logical processing is 1s by default
# Configure feign log level, and only debug is allowed
logging:
  level:
    com.fpa: debug
  • Create FeignLogConfig configuration class

    package com.fpa.consumer.config;
    
    import feign.Logger;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * Configure Feign log
     */
    @Configuration
    public class FeignLogConfig {
    
        @Bean
        public Logger.Level level(){
            return Logger.Level.FULL;
        }
    }
    
    
  • Go to GoodsFeignClient to start logging

    @FeignClient(value = "provider-app",configuration = FeignLogConfig.class)

    package com.fpa.consumer.interfaces;
    
    import com.fpa.consumer.bean.Goods;
    import com.fpa.consumer.config.FeignLogConfig;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    @FeignClient(value = "provider-app",configuration = FeignLogConfig.class)
    public interface GoodsFeignClient {
    
        @GetMapping("/goods/{id}")
        public Goods findOne(@PathVariable("id") int id);
    
    }
    
    
  • Restart the consumer and use the postman provider to view the console

    2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] <--- HTTP/1.1 200 (2199ms)
    2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] content-type: application/json;charset=UTF-8
    2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] date: Sat, 07 Aug 2021 07:23:15 GMT
    2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] transfer-encoding: chunked
    2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] 
    2021-08-07 15:23:15.753 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] {"id":1,"title": "Huawei mobile phone", "price":5999.0}
    2021-08-07 15:23:15.753 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient        : [GoodsFeignClient#findOne] <--- END HTTP (46-byte body)
    

Keywords: Java Distribution Spring Cloud feign

Added by abakash on Wed, 29 Dec 2021 17:54:44 +0200