springcloud openFeign 请求超时问题解决

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springcloud openFeign 请求超时问题解决相关的知识,希望对你有一定的参考价值。

参考技术A 后来查阅文档发现,feign的默认请求时间为1s,超过1s feign就报超时。这个可以通过配置修改掉

SpringCloud基础OpenFeign:远程通信

目录

1、基本介绍

1.1、简介

1.2、代码示例

2、组件特性

2.1、开启Gzip压缩

2.2、日志追踪

2.3、底层通信

3、多模块构建 

3.1、第一种构建方式

3.2、第二种构建方式


1、基本介绍

1.1、简介

Feign是一个声明式的伪RPC的REST客户端,它用了基于接口的注解方式,可以以Java接口注解的方式调用Http请求,从而将请求模板化。

Feign被广泛应用在SpringCloud的解决方案中,是学习基于SpringCloud微服务架构不可或缺的重要组件。

1.2、代码示例

在前一个项目的基础上,不再使用RestTemplate,而是改用OpenFeign

在SpringCloudProvideConsumerApplication启动类上添加注解@EnableFeignClients

@EnableFeignClients
@SpringBootApplication
public class SpringCloudProvideConsumerApplication {

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

}

添加后,增加接口IHelloController,在上面加上@FeignClient,在注解内填写需要连接的服务名称:spring-cloud-provider-service

@FeignClient("spring-cloud-provider-service")
public interface IHelloControllerFeign {

    @GetMapping("/hello")
    String sayHello();
}

调用时,就将IHelloController作为一个服务进行调用,得到的结果与使用RestTemplate是相同的。

@RestController
public class MyHelloController {

    @Autowired
    IHelloControllerFeign helloControllerFeign;

    @GetMapping("my")
    public String sayHello() {
        return helloControllerFeign.sayHello();
    }

}

2、组件特性

2.1、开启Gzip压缩

OpenFeign支持压缩传输数据,减少数据传输压力,主流浏览器同样支持Gzip压缩协议,可以直接使用。

配置项如下:

#开启Gzip压缩
feign.compression.request.enabled=true
#接受压缩的最小数据大小
feign.compression.request.min-request-size=2048
#回传数据接受Gzip压缩
feign.compression.response.enabled=true
#Gzip压缩格式
feign.compression.request.mime-types=text/xml
  1. feign.compression.request.enabled:开启Gzip压缩功能
  2. feign.compression.request.min-request-size:接受压缩的最小数据量,避免太小的数据压缩之后反而变大,增加传输压力
  3. feign.compression.response.enabled:是否对返回结果进行压缩
  4. feign.compression.request.mime-types:压缩格式,支持的格式有"text/xml", "application/xml", "application/json"

2.2、日志追踪

OpenFeign可以开启日志追踪,追踪固定的接口

需要在配置文件中增加:

logging.level.[com.my.p5.springcloudprovideconsumer.IHelloControllerFeign]=debug

 基本格式是logging.leve.[OpenFeign接口全路径名],数值是日志级别

增加FeignConfig类作为日志等级:

@Configuration
public class FeignConfig {

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

其中返回的常量值共有四个,分别是:

  1. FULL:所有日志信息
  2. HEADERS:包含BASIC级别的日志信息,额外包含请求头,响应头
  3. BASIC:仅记录请求方法,URL,响应状态码,执行时间
  4. NONE:不记录任何日志

在OpenFeign的接口中增加日志输出级别的类FeignConfig:

@FeignClient(name = "spring-cloud-provider-service", configuration = FeignConfig.class)
public interface IHelloControllerFeign {

    @GetMapping("/hello")
    String sayHello();
}

name为服务名,configuration为日志输出级别。 

最终执行后的日志输出:

 可以看到,日志输出的全部信息。

2.3、底层通信

feign采用的是代理模式,因此被称之为伪RPC。实际上,feign的底层是JDK提供的URLConnection,本身的性能不够好,如果想要替换,可以换成feign同样支持的okHttp。

想要替换为okHttp需要在pom文件中增加jar包:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

在配置文件中增加:

#关闭默认底层通信
feign.httpclient.enabled=false
#开启okHttp
feign.okhttp.enabled=true

3、多模块构建 

在实际开发过程中,服务端和消费端会共用一些代码,比如参数类,在这时,就需要进行多模块构建。

可以将代码模块分为服务模块,消费模块,API模块

创建一个新的项目,spring-cloud-user-provide作为父模块

在pom文件中添加父依赖:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
    </parent>

在dependencyManagement标签内添加spring-boot-parent的依赖,代表它的子项目都会依赖父项目的pom

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>${spring-boot-starter-parent.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

增加新的子项目,user-provide,user-api,provide-consumer,将父依赖替换为:

<parent>
    <groupId>com.my.example</groupId>
    <artifactId>spring-cloud-user-provider</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
</parent>

给user-provide,provide-consumer添加user-api依赖:

<dependency>
    <groupId>com.my.example</groupId>
    <artifactId>user-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

共有两种方式进行多模块构建。

3.1、第一种构建方式

在use-api增加两个类,User和UserClient

public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
@FeignClient("spring-cloud-user-provide")
public interface UserClient {

    @GetMapping("/user")
    public User queryUser();
}

在服务端增加UserController,在引入user-api的情况下,可以直接使用User类。

@RestController
public class UserController {

    @GetMapping("/user")
    public User queryUser() {
        User user = new User();
        user.setName("Lily");
        user.setAge(18);
        return user;
    }
}

在消费端增加HelloController,在引入user-api的情况下,可以直接使用User类,可以将UserClient作为类似于Service层的类进行调用。

@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private UserClient userClient;

    @GetMapping("/user")
    public String user() {
        User user = userClient.queryUser();
        return "hello " + user.getName();
    }
}

构建完成后,访问:http://localhost:8082/hello/user

3.2、第二种构建方式

在data-api增加三个类,Data,DataFeign和IDataService

public class Data {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 feign是可以继承接口的,这样就可以不用实现方法

@FeignClient("spring-cloud-data-provide")
public interface DataFeign extends IDataService{
}

将接口内的方法增加GetMapping访问路径 

public interface IDataService {

    @GetMapping("/data")
    Data sayHello();
}

在data-provider中添加一个类,对接口进行实现:

@RestController
public class DataServiceImpl implements IDataService {

    @Override
    public Data sayHello() {
        Data data = new Data();
        data.setName("Lily");
        data.setAge(18);
        return data;
    }
}

在provider-consumer中添加一个类:

@RestController
@RequestMapping("/show")
public class ShowController {

    @Autowired
    private DataFeign dataFeign;

    @GetMapping("/data")
    public String data() {
        Data data = dataFeign.sayHello();
        return "hello " + data.getName();
    }
}

构建完成后,访问:http://localhost:8082/show/data

我的公开码云代码地址:springclouduserprovider: springcloud测试

以上是关于springcloud openFeign 请求超时问题解决的主要内容,如果未能解决你的问题,请参考以下文章

springcloud 整合openFeign

SpringCloud基础OpenFeign:远程通信

SpringCloud(15)——OpenFeign超时控制

最适合新手入门的SpringCloud教程 7—OpenFeign「F版本」

SpringCloud --- 服务调用 (Ribbon,OpenFeign)

SpringCloud --- 服务调用 (Ribbon,OpenFeign)