SpringCloud-服务之间如何进行调用(OpenFeign)

Posted 赵晓东-Nastu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud-服务之间如何进行调用(OpenFeign)相关的知识,希望对你有一定的参考价值。

一、概述

1、OpenFeign是什么?

Feign是一个声明式WebService客户端,使用Feign能让编写Web Service客户端更加简单,它的使用方法是定义一个服务接口然后在上面添加注解 。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡

2、能干嘛?

1、Feign能干什么?

Feign编写Java Http客户端变得更加容易

前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成一套模板化的调用方法,但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多次调用,所以通常都会针对每个微服务自行封装一些客户端类来保证这些依赖服务的调用,所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可)。

 

2、Feign集成了Ribbon

利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。

3、Feign和OpenFeign两者区别?

 

二、OpenFeign使用步骤

1、接口+注解

(微服务调用接口+@FeignClient)

微服务调用接口:指的是提供者所提供的接口和消费者想要调用的接口吻合才能匹配

2、新建cloud-consumer-feign-order80,Feign用在消费端。

3、POM

这里其实就是加入了openfeign


    <dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--web-->
        <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>

4、YML 

feign就是一个客户端所以就不注册进eureka

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.atguigu.springcloud.service.PaymentFeignService: debug

 

5、主启动

因为加了openfeign注解,所以需要在主启动上面加上EnableFeignClients去启动。

6、业务类

现在8001提供了两个

 消费者

现在消费者调用服务者其实是和服务者的controller保持一致的,

 

 

所以说总结一下业务的话,第一步在消费端的service接口中加入FeignClient然后调用接口即可。

 7、测试

先启动eureka 

再启动微服务8001

再启动OpenFeign

 

这里我只启动了3个服务,一个是注册中心Eureka一个是服务的提供者,另一个就是消费者OrderFeign

 

三、OpenFeign超时控制

消费者去掉用服务者一定会存在超时

所以两个需要约定好

1、超时设置,故意设置超时演示出错情况

服务提供方8001故意写暂停程序

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout(){
        //暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return serverPort;
    }

服务消费方80添加超时方法 PaymentFeignService

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

服务消费方80家假超时方法 OrderFeignController

    @GetMapping(value = "/consumer/payment/feign/timeout")
    public  String paymentFeignTimeout(){
        //openfeign-ribbon,客户端一般默认等待1秒钟
        return paymentFeignService.paymentFeignTimeout();
    }

 

测试:

http://localhost/consumer/payment/feign/timeout

错误页面

openfeign默认等待1秒钟,超过后报错 

 

默认Feign客户端只等待一秒钟,但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错了。

为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。

2、YML文件里需要开启OpenFeign客户端超时控制

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

四、OpenFeign日志增强

Feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解Feign中Http请求的细节。

说白了就是对Feign接口的调用情况进行监控和输出

OpenFeign日志打印功能:

1、日志级别

NONE: 默认的,不显示任何日志;

BASIC:仅记录请求方法、URL、响应状态码及执行时间

HEADERS:除了BASIC中定义的信息之外还有请求和响应的头信息

FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据

2、配置日志bean

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

3、YML文件里需要开启日志的Feign客户端

logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.atguigu.springcloud.service.PaymentFeignService: debug

 4、后台日志查看

http://localhost/consumer/payment/get/1

]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@3e5f28b6
2021-05-31 10:12:43.790 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] <--- HTTP/1.1 200 (341ms)
2021-05-31 10:12:43.791 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] connection: keep-alive
2021-05-31 10:12:43.791 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] content-type: application/json
2021-05-31 10:12:43.791 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] date: Mon, 31 May 2021 02:12:43 GMT
2021-05-31 10:12:43.791 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] keep-alive: timeout=60
2021-05-31 10:12:43.791 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] transfer-encoding: chunked
2021-05-31 10:12:43.791 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] 
2021-05-31 10:12:43.793 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] {"code":200,"message":"插入数据库成功","data":{"id":1,"serial":"zxd"}}
2021-05-31 10:12:43.794 DEBUG 548 --- [p-nio-80-exec-1] c.a.s.service.PaymentFeignService        : [PaymentFeignService#getPaymentById] <--- END HTTP (77-byte body)
2021-05-31 10:12:44.635  INFO 548 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: CLOUD-PAYMENT-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

 

以上是关于SpringCloud-服务之间如何进行调用(OpenFeign)的主要内容,如果未能解决你的问题,请参考以下文章

springcloud学习2:使用feign进行微服务之间的调用

SpringCloud学习之服务注册中心

springcloud 整合openFeign

SpringCloud-笔记5-中服务间两种调用方式-Feign

springcloudalibaba架构(31):SpringCloud实现用户信息在微服务之间传递(Feign和Dubbo)

SpringCloud——服务治理中心Eureka