[04] 入门Spring Cloud_OpenFeign 模块间调用

一、OpenFeign 模块间调用

现在的项目中已经使用 RestTemplate 实现模块间的调用,为什么还要使用 OpenFeign

因为 RestTemplate 是基于类调用,每次调用都需要 new 出 RestTemplate 类,耦合性很强。

1. OpenFeign 介绍

介绍 OpenFeign 之前先来介绍 Feign:

  • feign 是一个声明式的Web服务客户端,让编写Web服务客户端变得非常容易,只需要创建一个接口并在接口上添加注释即可
  • Spring Cloud 对 Feign 进行了封装,使其支持了 SpringMVC 标准注解和 HttpMessageConverters 。 Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。

使用的目的为了用接口的方式让模块之间的调用更加灵活,而不是 new 出一个个的类

Feign 集成了 Ribbon ,与 Ribbon 不同的是,通过 Feign 只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。

OpenFeign 是 Spring Cloud 在 Feign 的基础上继续进行封装,支持了 SpringMVC 的注释,如@RequesMapping等等。
OpenFeign 的 @FeignClient 可以解析 SpringMVC 的 @RequesMapping 注释下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

2. 使用方式

服务提供方(生产者)和服务调用方(消费者)在注册中心注册后,服务调用方由原来的 Ribbon + RestTemplate 的方式改为使用 OpenFeign 方式调用,使用方式为:

微服务调用接口 + @FeignClient

在这里插入图片描述

二、当前项目结构介绍

当前项目中包含四个模块:

在这里插入图片描述

  • 公有API:cloud-api-commons
  • 服务提供者: cloud-provider-payment8001/8002 (端口号8001 和 8002 )
  • 服务消费者: cloud-consumer-order80 (端口号80 )
  • 注册中心 Eureka: cloud-eureka-server7001(端口号7001 )

前文链接: https://blog.csdn.net/weixin_42547014/article/details/120334570
项目源码:https://gitee.com/zhangchouchou/spring-cloud-demo/tree/46f877311e6c491aaa766e69d41f6f12d1256f01/

三、项目中添加 Feign

1. 新建模块

新建一个模块,命名为 cloud-consumer-feign-order80 ,添加方式依旧为 Maven

在这里插入图片描述

2. POM 引入依赖

注:OpenFeign 也是自带 Ribbon

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloudDemo</artifactId>
        <groupId>org.zjh.springclouddemo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-feign-order80</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

        <!--OpenFeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!--Eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.zjh.springclouddemo</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <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>

</project>

3. 添加 YML

server:
  port: 80

spring:
  application:
    name: cloud-consumer-feign-order80

eureka:
  client:
#    是否注册到eureka
    register-with-eureka: true
#    是否发现相关服务
    fetch-registry: true
#    指定路径
    service-url:
      defaultZone: http://localhost:7001/eureka

4. 创建启动类

在启动类上添加 @EnableFeignClients 注解,该注解只在服务调用方添加即可。

@SpringBootApplication
// Eureka客户端
@EnableEurekaClient
//服务调用方开启Feign
@EnableFeignClients
public class FeignConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class,args);
    }
}

5. 添加调用接口

添加接口 PaymentFeignService

目录结构

在这里插入图片描述

//作为组件被发现
@Component
//指定远程调用的微服务的名称
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    @GetMapping("/user/get/{id}")
    public CommonResult<User> getByID(@PathVariable("id")Integer id);
}

6. 实现 Controller

@RestController
@Slf4j
public class FeignController {

    @Autowired
    private PaymentFeignService paymentFeignService;  //调用远程的微服务接口

    @GetMapping("/consumer/user/get/{id}")
    public CommonResult<User> getByID(@PathVariable("id")Integer id){
        return paymentFeignService.getByID(id);
    }
}

至此便实现了模块间接口的远程调用。

7. 验证

启动注册中心 -> 启动8001端口模块 -> 启动新建的模块

刷新注册中心看新建的服务是否注册上

在这里插入图片描述

注册成功后,访问新启动的80端口进行数据获取

在这里插入图片描述

数据成功获取,说明配置成功。

四、请求超时处理

模块之间的调用很有可能出现请求超时的情况,给 8001 端口的生产者添加一个新的请求,该请求不做任何查询,在方法中等待几秒,如下所示:

	@GetMapping("/user/timeout")
    public String feignTimeout(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //返回端口号
        return port;
    }

再在刚刚添加的 Feign 方式的消费者的接口中添加方法

在这里插入图片描述
最后在Controller中添加请求

 @GetMapping("/consumer/user/timeout")
    public String feignTimeout(){
        return paymentFeignService.feignTimeout();
    }

重新启动服务并访问路径,因为 OpenFeign 默认等待1秒,所以会出现请求超时的错误

在这里插入图片描述
处理方式很简单,设置超时时间。

在 YML 中开启 OpenFeign 客户端超时控制。

ribbon:
  ReadTimeout: 5000   #读取的超时时间
  ConnectTimeout: 5000  #链接的超时时间
  MaxAutoRetries: 1  #同一台实例最大重试次数,不包括首次调用
  MaxAutoRetriesNextServer: 1  #重试负载均衡其他的实例最大重试次数,不包括首次调用
  OkToRetryOnAllOperations: false  #是否所有操作都重试

当然,这种方法治标不治本,真正的解决方式是使用断路器(Hystrix),会在后文讲解。

五、日志打印

留意一下控制台可以发现一些打印出来的请求信息, Feign 支持打印接口调用情况,方便进行接口监控。

在这里插入图片描述

日志级别:

  • NONE:默认的,不显示任何日志
  • BASIC:仅记录请求方法、URL、响应状态码及执行时间。
  • HEADERS: 除了BASIC中定义的信息外,还有请求和响应头信息
  • FULL: 除了HEADERS中定义的信息外,还有请求及响应的正文及元数据

配置日志 Bean

@SpringBootConfiguration
public class FeignConfig {

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

YML 中开启日志的 Feign 客户端

logging:
  level:
    org.zjh.springcloud.service.PaymentFeignService: debug

重启后再次查询信息,可以看到打印的日志信息

2021-09-17 17:06:53.825  INFO 808 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: CLOUD-PAYMENT-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] <--- HTTP/1.1 200 (2906ms)
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] connection: keep-alive
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] content-type: application/json
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] date: Fri, 17 Sep 2021 09:06:55 GMT
2021-09-17 17:06:55.224 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] keep-alive: timeout=60
2021-09-17 17:06:55.224 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] transfer-encoding: chunked
2021-09-17 17:06:55.224 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] 
2021-09-17 17:06:55.225 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] {"code":200,"message":"查询成功","data":{"id":6,"name":"吴","phone":"19804563454","sex":"女"}}
2021-09-17 17:06:55.225 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] <--- END HTTP (100-byte body)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值