【真会玩】- SpringCloud Netflix 实战笔记 -【OpenFeign】


在这里插入图片描述

友情提醒

  • 文末获取【真会玩】- SpringCloud Netflix 实战系列Postman在线脚本Github仓库实战源码
  • 【真会玩】- SpringCloud Netflix 实战系列有概念有实战,考验动手能力,如果实战中有操作没有达到与本文同等效果的请先仔细检查个人操作与文中相关内容是否一致,如检查无误请私信或评论区留言~

在这里插入图片描述

Feign和OpenFeign

  • Feign是Netflix开发的声明式、模板化的HTTP请求客户端。可以更加便捷、优雅地调用http api
  • Feign有一套自己的注解,不支持Spring MVC的注解
  • OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping
  • OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解的接口,
    并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
  • OpenFeign会根据带有注解的函数信息构建出网络请求的模板,在发送网络请求之前,OpenFeign会将函数的参数值设置到这些请求模板中
  • 使用OpenFeign提供的注解修饰定义网络请求的接口类,就可以使用该接口的实例发送RESTful的网络请求。还可以集成RibbonHystrix,提供负载均衡断路器

工程搭建

新建Feign-ApiFeign-ProviderFeign-Consumer工程来演示Feign的使用,现在我们开始创建工程,按以下顺序逐步创建

  • 新建Service-Api
  • 新建Feign-Provider
  • 新建Feign-Consumer

Service-Api搭建

在这里插入图片描述

Service-Api只需要添加一个Spring Web依赖即可

在这里插入图片描述

新建ServiceApi接口,暴露一个/pingFeignProvider

@RequestMapping("")
public interface ServiceApi {
    
    @GetMapping("/pingFeignProvider")
    String pingFeignProvider();
}

FeignProvider搭建

image-20220921002204196

Feign-Provider这边我们选上Spring WebEureka Discovery Client两个依赖即可,这边的SpringBoot版本不用管,本次用的SpringCloud版本为 Hoxton.SR12, 所以SpringBoot版本要选2.3.12.RELEASE 这里是没有,我们稍后手动到pom文件里面修改版本即可

在这里插入图片描述

修改pom文件中spring-boot-starter-parent - version2.3.12.RELEASE

在这里插入图片描述

修改spring-cloud.versionHoxton.SR12

在这里插入图片描述

新建application.yml文件并添加以下配置

server:
  port: 9090

spring:
  application:
    name: FeignProvider

eureka:
  client:
    service-url:
      #向eureka发起注册请求
      defaultZone: http://RhysNi:123456@eureka1.com:7901/eureka/
  healthcheck:
    enabled: true
  instance:
    #查找主机
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

Service-Api作为依赖添加到Feign-provider

  • groupId记得根据自己定义的进行修改
<dependency>
  <groupId>com.rhys</groupId>
  <artifactId>Service-Api</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

新建FeignProviderController,由于我们将Service-Api作为依赖添加到Feign-provider了,可以直接实现ServiceApi接口

那有兄弟要问了:“这样的话我如果想像以前一样直接调用这个接口该怎么调用呢?”

  • http://localhost:9090/pingFeignProvider 这样就可以了,照常调用就可以了,接口路径保持ServiceApi中的路径相同即可
@RestController
public class FeignProviderController implements ServiceApi {

    @Override
    public String pingFeignProvider() {
        return "Ping Feign Provider Success";
    }
}

Feign-Consumer搭建

在这里插入图片描述

同样的在左侧栏里面找到并勾选Spring WebEureka Discovery ClientOpenFeign三个依赖

在这里插入图片描述

Feign-Provider一样方式修改SpringCloudSpringBoot版本 (修改方式同上,忘记的点击前方关键词跳转查看)

新建application.yml文件并添加以下配置

server:
  port: 9080

spring:
  application:
    name: FeignConsumer

eureka:
  client:
    service-url:
      #向eureka发起注册请求
      defaultZone: http://RhysNi:123456@eureka1.com:7901/eureka/
  healthcheck:
    enabled: true
  instance:
    #查找主机
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

特殊说明:

  • 上边的defaultZone配置项里面我带了一个RhysNi:123456这个是因为我的Eureka-Server开启了Spring Security安全认证,所以需要用户名密码才能成功注册到Eureka,如果没有集成过Spring Security把这个defaultZone配置的值改为http://eureka1.com:7901/eureka/即可
  • 还有一点,defaultZone配置项里面eureka1.com这个是因为我在本地配置了hostname映射了127.0.0.1,想了解怎么配置的兄弟点击跳转查看配置方式

由于我们接下来要用Feign调用接口,所以要在Feign-Consumer的启动类上添加@EnableFeignClients注解以支持

@SpringBootApplication
@EnableFeignClients
public class FeignConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class, args);
    }
}

Service-Api作为依赖添加到Feign-consumer

  • groupId记得根据自己定义的进行修改
<dependency>
  <groupId>com.rhys</groupId>
  <artifactId>Service-Api</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

新建FeignConsumerApi接口,在接口上添加@FeignClient注解并继承ServiceApi接口(这样就不用我们再次声明一次接口了,减少冗余代码),@FeignClient注解的name属性填我们要调用的Feign-Provider的服务名,我们刚设置的是FeignProvider,这样就可以走Ribbon进行负载均衡了

此时便可以在需要调用的类中注入ServiceApi调用Feign-Provider的接口了

@FeignClient(name = "FeignProvider")
public interface FeignConsumerApi extends ServiceApi {
}

新建FeignConsumerController并注入FeignConsumerApi

@RestController
public class FeignConsumerController {
    @Resource
    private FeignConsumerApi feignConsumerApi;

    @GetMapping("/testOpenFeign")
    public String testOpenFeign() {
        return feignConsumerApi.pingFeignProvider();
    }
}

在这里插入图片描述

可以看到所有服务都在Eureka注册成功了

在这里插入图片描述

调用http://localhost:9080/testOpenFeign接口

在这里插入图片描述

超时案例

Feign-Consumer服务调用方模块中添加如下配置

ribbon:
  #连接超时(ms)
  ConnectTimout: 1000
  #逻辑响应超时(ms)
  ReadTimout: 3000

我们模拟一下超时场景,在FeignProviderController中让这个接口睡上5秒

@RestController
public class FeignProviderController implements ServiceApi {
    private AtomicInteger requestCount = new AtomicInteger();

    @Value("${server.port}")
    private String port;

    @Override
    public String pingFeignProvider() {
        try {
            System.out.println("开始模拟超时");
            TimeUnit.MILLISECONDS.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException();
        }
        return "Ping Feign Provider Port:" + port + " Success Count:"+requestCount.incrementAndGet();
    }
}

我们配置的逻辑响应超时是3s,所以当Feign-Consumer调用Feign-Provider/pingFeignProvider接口时就会认为接口响应超时了

image-20220922114222007

Ribbon对于超时还有重试机制,比如咱们起的Feign-Provider服务为多实例,Ribbon则会基于负载均衡对其余节点依次执行重试机制

重试机制

关于重试机制也是有配置项可配的,一起来看看怎么配

  • Feign默认支持Ribbon

  • Ribbon的重试机制和Feign的重试机制有冲突,所以源码中默认关闭Feign的重试机制,使用Ribbon的重试机制

  • ribbon重试机制,请求失败后,每6秒会重新尝试

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

注意,接下来启动服务才是本次演示讲究的地方

  • 睡眠的那套代码启动一个实例
  • 在注释掉睡眠代码,启动两个实例
  • 总共三个实例,模拟Ribbon的重试和服务降级(非熔断降级),这边降级意思就是重试一定次数后,在一定时间内(一般6秒)就不会再去调这个服务节点,6秒后再有请求过来会再次尝试去调用该服务节点

在这里插入图片描述

最后再调用Feign-Consumer/testOpenFeign接口

  • 可以看到每次调用到超时的节点时都会进行一次重试,一共是调用两次该接口,所以控制台每次都会打印两行模拟重试的提示信息,在重试还是失败的情况下会去调用其他节点进行重试,如果其他节点调用成功则返回

20220923_044253(1)

在这里插入图片描述

源码&脚本获取地址

  • Postman脚本https://www.getpostman.com/collections/8a0954746646f0dee9a6
    • 脚本可直接复制到Postman使用Link方式导入
  • 实战源码仓库https://github.com/RhysNi/SpringCloudFamilyMeals.git

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倪倪N

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值