Internet giant technology-HTTP request-Springboot integrates Feign to implement Http service calls more elegantly

Table of contents

1. SpringBoot quickly integrates Feign

1. Add Pom dependencies

2. Add annotations to the startup class

3. Reference Feign service

2. Three ways to add Header to the request

1. Add a fixed header

2. Add header through interface signature

3. Add header dynamically

3. Add a timeout configuration to the request

1. Default timeout

3. Timeout exception

4. Global timeout configuration

5. Set timeout configuration for individual services

4. Configure the client load balancing mode for the request

Five, Feign log

1. Log level

2. Log configuration class

3. Configuration file

Six, high-level configuration

Seven, Feign and Springboot version

8. Technical issues

no suitable HttpMessageConverter found for response type



This chapter explains key goals and user-oriented

Objectives of this chapter

Understand the principle of feign

Master the use of feign

Learn how to set feign's various headers

Learn to feign log control

Understand feign advanced configuration items

Other Development Considerations

user-oriented Beginner, middle and advanced R&D students

Many times, we see that when some high-level architecture students are writing Http service calls, when debugging and tracking codes, they only have interface signatures, and they do not write some calling process code like okhttp. The code looks refreshing, elegant and logical. , after reading this article, you will master its implementation plan, and provide a demo to help you complete the actual combat. If you have technical questions, you can ask for advice by private message;

1. SpringBoot quickly integrates Feign

1. Add Pom dependencies

 <properties>
        <spring-cloud-feign.version>3.1.3</spring-cloud-feign.version>
    </properties>

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.7.10</version>
</parent>
<dependencies>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
   <version>${spring-cloud-feign.version}</version>
</dependency>
</dependencies>

2. Add annotations to the startup class

@EnableFeignClients

3. Reference Feign service

@RestController
@RequestMapping("/stock")
public class StockController {

    @Autowired
    private LocalFeignService service;

    @GetMapping("/get")
    public String get(){
        service.add("10");
        return "Hello world";
    }
}

2. Three ways to add Header to the request

1. Add a fixed header

@RestController
public class HomeController {

    @Resource
    private FeignClientService feignClientService;

    

    @RequestMapping(value = "/add")
    public String add(@RequestBody FeignReq req) {
        return "ok";
    }

   
    @RequestMapping("/test-add")
    public Object testAdd() {
        FeignReq req = new FeignReq();
        req.setId(System.currentTimeMillis());
        return feignClientService.add(req);
    }

}

Add a fixed header value to the headers parameter of the @PostMapping annotation, and also include some configuration items read from the configuration file as the header value

@Component
@FeignClient(name = "feignClientService", url = "http://localhost:8081")
public interface FeignClientService {

    @PostMapping(value = "/add", headers = {"Authorization=myFeignSignToken", "Content-Type=text/plain", "App=${my.name}"})
    public String add(@RequestBody FeignReq req);

}

Browser access: http://localhost:8081/test-add

2. Add header through interface signature

@RestController
public class HomeController {



    @Resource
    private FeignClientService feignClientService;


    @PostMapping(value = "/query")
    public String query(@RequestParam("queryName") String queryName) {

        return queryName + "ok";
    }


    @RequestMapping("/test-query")
    public Object testQuery() {
        Map<String, String> map = new HashMap<>();
        map.put("token", "ikong_token"+System.currentTimeMillis());
        return feignClientService.query("ikong", map);
    }

}

The focus is on the headers of the Map type. Here, the Map object is converted into a request header through the @RequestHeader annotation of the interface signature

@Component
@FeignClient(name = "feignClientService", url = "http://localhost:8081", configuration = TestRequestInterceptor.class)
public interface FeignClientService {

    @PostMapping(value = "/query")
    public String query(@RequestParam("queryName") String queryName, @RequestHeader Map<String, String> headers);

}

Browser access: http://localhost:8081/test-query

3. Add header dynamically

@RestController
public class HomeController {


    @Resource
    private FeignClientService feignClientService;

    @RequestMapping("/search")
    public Object search(@RequestBody FeignReq req) {
        return "ok";
    }

   
    @RequestMapping("/test-search")
    public Object testSearch() {
        FeignReq req = new FeignReq();
        req.setId(System.currentTimeMillis());
        return feignClientService.search(req);
    }


}

@Component
@FeignClient(name = "feignClientService", url = "http://localhost:8081", configuration = TestRequestInterceptor.class)
public interface FeignClientService {


    @PostMapping("/search")
    public String search(@RequestBody FeignReq req);

}

Inject configuration = TestRequestInterceptor.class through FeignClient annotation, and realize header dynamic addition capability in TestRequestInterceptor


public class TestRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        template.header(HttpHeaders.AUTHORIZATION, createApiSign());
    }

    /**
     * 创建接口签名
     *
     * @return
     */
    private String createApiSign() {
        return UUID.randomUUID().toString();
    }

}

Browser access: http://localhost:8081/test-search

3. Add a timeout configuration to the request

1. Default timeout

connectiontimeout : 10s,readtimeout : 60s

  public static class Options {
 
    private final int connectTimeoutMillis;
    private final int readTimeoutMillis;
 
    public Options(int connectTimeoutMillis, int readTimeoutMillis) {
      this.connectTimeoutMillis = connectTimeoutMillis;
      this.readTimeoutMillis = readTimeoutMillis;
    }
 
    public Options() {
      this(10 * 1000, 60 * 1000);
    }
 
    /**
     * Defaults to 10 seconds. {@code 0} implies no timeout.
     *
     * @see java.net.HttpURLConnection#getConnectTimeout()
     */
    public int connectTimeoutMillis() {
      return connectTimeoutMillis;
    }
 
    /**
     * Defaults to 60 seconds. {@code 0} implies no timeout.
     *
     * @see java.net.HttpURLConnection#getReadTimeout()
     */
    public int readTimeoutMillis() {
      return readTimeoutMillis;
    }
  }

3. Timeout exception

exception:feign.RetryableException: connect timed out executing POST http://xxx.ik.com/your/api

4. Global timeout configuration

feign.client.config.default.connectTimeout=5000
feign.client.config.default.readTimeout=5000

5. Set timeout configuration for individual services

 To implement different timeouts for different services, you can configure them as follows

feign.client.config.yourService.connectTimeout=5
feign.client.config.yourService.readTimeout=5

4. Configure the client load balancing mode for the request

OpenFeign is just a Rest client and does not have any load balancing operations.  The bottom layer of OpenFeign still calls the Netflix Ribbon load balancing component, so how do we modify the load balancing strategy when we use OpenFeign to implement service calls?

Customize Ribbon's load balancing configuration

@Configuration
// name为服务名
@RibbonClient(name = "my-provider", configuration = MyLoadBalanceConfiguration.class)
public class MyLoadBalanceConfiguration {

    @Bean
    public IRule ribbonRule() {
        return new RandomRule(); // 采用随机策略
    }
}

We are using the random strategy here, and the default is the round-robin strategy.

Ribbon provides optional load balancing classification

  1. Random strategy - RandomRule
  2. Polling strategy - RoundRobinRule Note: Ribbon default strategy
  3. Retry strategy - RetryRule
  4. Minimum Concurrency Policy - BestAvailableRule
  5. Available filtering strategy - AvailabilityFilteringRule, filter out those back-end servers marked as circuit tripped because of continuous connection failure, and filter out those back-end servers with high concurrency (active connections exceed the configured threshold), the performance is second only to the lowest concurrency strategy.
  6. Response time weighting strategy ——WeightedResponseTimeRule, calculate the server response time every 30 seconds, and use the response time as the weight. The shorter the response time, the greater the probability of being selected.
  7. Zone Tradeoff Strategy ——ZoneAvoidanceRule

Suggestions for using Ribbon's load balancing strategy
In general, it is recommended to use the lowest concurrency strategy, which has much higher performance than the default polling strategy.

Five, Feign log

Feign's log is based on the debug log mode. Whether it is global configuration or local configuration, code configuration or property configuration, you need to first change the log mode to debug mode: (The following is an example of calling the log mode of the FeignClientService interface )

1. Log level

OpenFeign's log levels are

  • NONE: By default, no logs are displayed.

  • BASIC: Only log the request method, URL, response status code, and execution time.

  • HEADERS: In addition to the custom information in BASIC, there are request and response headers.

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

2. Log configuration class

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

3. Configuration file

logging:
  level:
  *[feign日志以什么级别监控哪个接口]:
  com.ik.ikong.service.FeignClientService: debug

Six, high-level configuration

Seven, Feign and Springboot version

The version comparison relationship is as follows, for details, you can also click the link here to view the latest version compatibility relationship on the official website

8. Technical issues

Idea reports an error when calling the interface

no suitable HttpMessageConverter found for response type

resolution process

1. Let go of the log

@Configuration
public class FeignConfiguration {

    @Bean
    public feign.Logger logger() {
        return new Slf4jLogger();
    }
    @Bean
    public Logger.Level level() {
        return Logger.Level.FULL;
    }
}
logging:
  level:
    feign.Logger: debug

log detailed

From the released log, in the header returned by the interface: content-type: text/html; charset=UTF-8

Although I added produces and consumes to the interface signature

@PostMapping(value = "/xxxxx/your/api", produces = "application/json;charset=utf-8", consumes = "application/json;charset=utf-8")

It can be seen that there is no effect, and it is still abnormal: no suitable HttpMessageConverter found for response type

It is guessed that the native http return value only performs generic deserialization processing on the application/json type, which is the content-type: text/html returned by the interface; it cannot perform json deserialization processing, so add this type of json Deserialization processing;

@Bean
    public HttpMessageConverters customConverters() {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_HTML,MediaType.APPLICATION_JSON));
        return new HttpMessageConverters(false, Arrays.asList(mappingJackson2HttpMessageConverter, new StringHttpMessageConverter()));
    }

重点在mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_HTML,MediaType.APPLICATION_JSON));

Finally, the json deserialization with content-type: text/html was successfully completed;

Reference: Spring Cloud

Feign implements Http calls between services. _feign http call_Half-life i's Blog-CSDN Blog

Guess you like

Origin blog.csdn.net/philip502/article/details/131351905