文章

声明式调用

声明式调用

在 Spring Cloud 中,目前使用的声明式调用组件,只有:

  • spring-cloud-openfeign ,基于 Feign 实现。

如果熟悉 Dubbo 胖友的会知道,Dubbo 的 Service API 接口,也是一种声明式调用的提现。

艿艿:注意噢,Feign 并非 Netflix 团队开发的组件。所有基于 Netflix 组件都在 spring-cloud-netflix 项目下噢。

Feign

Feign 是受到 Retrofit、JAXRS-2.0 和 WebSocket 启发的 Java 客户端联编程序。Feign 的主要目标是将Java Http 客户端变得简单。

具体 Feign 如何使用,可以看看 《对于 Spring Cloud Feign 入门示例的一点思考》 。

有一点要注意,Feign 并非一定要在 Spring Cloud 下使用,单独使用也是没问题的。

Feign 实现原理?

Feign的一个关键机制就是使用了动态代理。咱们一起来看看下面的图,结合图来分析:

  • 首先,如果你对某个接口定义了 @FeignClient 注解,Feign 就会针对这个接口创建一个动态代理。
  • 接着你要是调用那个接口,本质就是会调用 Feign 创建的动态代理,这是核心中的核心。
  • Feig n的动态代理会根据你在接口上的 @RequestMapping 等注解,来动态构造出你要请求的服务的地址。
  • 最后针对这个地址,发起请求、解析响应。

Feign 和 Ribbon 的区别?

Ribbon 和 Feign 都是使用于调用用其余服务的,不过方式不同。

  • 启动类用的注解不同。
    • Ribbon 使用的是 @RibbonClient 。
    • Feign 使用的是 @EnableFeignClients 。
  • 服务的指定位置不同。
    • Ribbon 是在 @RibbonClient 注解上设置。
    • Feign 则是在定义声明方法的接口中用 @FeignClient 注解上设置。
  • 调使用方式不同。
    • Ribbon 需要自己构建 Http 请求,模拟 Http 请求而后用 RestTemplate 发送给其余服务,步骤相当繁琐。
    • Feign 采使用接口的方式,将需要调使用的其余服务的方法定义成声明方法就可,不需要自己构建 Http 请求。不过要注意的是声明方法的注解、方法签名要和提供服务的方法完全一致。

Feign 是怎么和 Ribbon、Eureka 整合的?

结合 「 Ribbon 是怎么和 Eureka 整合的?」 问题,并结合如下图:

  • 首先,用户调用 Feign 创建的动态代理。
  • 然后,Feign 调用 Ribbon 发起调用流程。
    • 首先,Ribbon 会从 Eureka Client 里获取到对应的服务列表。
    • 然后,Ribbon 使用负载均衡算法获得使用的服务。
    • 最后,Ribbon 调用 Feign ,而 Feign 调用 HTTP 库最终调用使用的服务。

这可能是比较绕的,艿艿自己也困惑了一下,后来去请教了下 didi 。因为 Feign 和 Ribbon 都存在使用 HTTP 库调用指定的服务,那么两者在集成之后,必然是只能保留一个。比较正常的理解,也是保留 Feign 的调用,而 Ribbon 更纯粹的只负责负载均衡的功能。

想要完全理解,建议胖友直接看如下两个类:

  • LoadBalancerFeignClient ,Spring Cloud 实现 Feign Client 接口的二次封装,实现对 Ribbon 的调用。
  • FeignLoadBalancer ,Ribbon 的集成。

集成的是 AbstractLoadBalancerAwareClient 抽象类,它会自动注入项目中所使用的负载均衡组件。

  • LoadBalancerFeignClient =》调用=》 FeignLoadBalancer 。

聊聊 Feign 重试机制?

可以看看 《Spring Cloud 各组件重试总结》 文章。因为 Ribbon 和 Feign 都有重试机制,在整合 Ribbon 的情况下,不使用 Feign 重试,而是使用 Ribbon 的重试。

本文由作者按照 CC BY 4.0 进行授权