【Spring Cloud Alibaba】(二)微服务调用组件Feign原理+实战

news2025/7/11 5:32:18

CSDN成就一亿技术人

系列目录

【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战


本文目录

  • 系列目录
  • 前言
  • 什么是RPC?
  • Feign和OpenFeign都是什么?
  • HTTP调用 vs Feign(RPC)调用
  • 单独使用Feign实战
  • Feign核心源码解读
  • Feign整体设计架构
  • Spring Cloud OpenFeign实战
  • Feign在实际项目的通常做法
  • 最后


前言

通过上文,我们掌握了Spring Cloud Alibaba微服务框架的初始环境搭建,并能通过Nacos注册中心的服务注册和发现,配合RestTemplate和Ribbon,实现2个服务之间通过服务名进行远程调用。
实际上,微服务之间的调用还有更简单、更方便、更强大的调用方式,那就是RPC调用!本文所讲的微服务调用组件Feign,正是RPC框架之一!
本文会循序渐进的从Feign讲到OpenFeign,并会讲到Feign核心原理实际项目使用OpenFeign的通常做法

  • 单独使用Feign实战,实现2个服务之间的RPC调用;
  • Feign核心源码解读;
  • Feign整体设计架构预览;
  • Spring Cloud Alibaba快速整合Feign,实现2个服务之间通过Nacos服务注册发现的RPC调用;
  • Feign在实际项目的通常做法。

什么是RPC?

RPC(Remote Produce Call),即远程过程调用,目的是:调用[远程服务方法]像调用[本地方法]一样!


Feign和OpenFeign都是什么?

Feign是RPC框架中的一种,是Netflix开发的声明式、模板化的HTTP客户端,底层依然是走的HTTP调用,但表现形式是接口调用,可以帮助我们更加便捷、优雅地调用HTTP API,就像调用本地方法一样方便。
它通过扩展集成了Netflix Ribbon,从而拥有负载均衡的功能,默认是基于配置来提供服务实例列表

OpenFeign是指Spring Cloud OpenFeign,是Spring Cloud开发的,对Feign进行了增强,使其支持Spring MVC注解,还整合了Spring Cloud Netflix Ribbon,从注册中心获取服务实例(在Spring Cloud Alibaba框架中的注册中心默认是Nacos),从而使得Feign与Spring Cloud整合。


HTTP调用 vs Feign(RPC)调用

回顾一下RestTemplate方式的服务调用(gg-user是服务名):

@Autowired
private RestTemplate restTemplate;

@GetMapping("/getUserName")
public String getUserName(@RequestParam("id") Integer id) {
    String url = String.format("http://%s/user?id=%s", "gg-user", id);
    return restTemplate.exchange(url, HttpMethod.GET, null, String.class).getBody();
}

换成Feign调用,感受一下效果:

@Autowired
private UserService userService;

@GetMapping("/getUserName")
public String getUserName(@RequestParam("id") Integer id) {
    return userService.getUserName(id);
}

What? Feign这个是远程调用?

对,这就是远程调用,丝毫看不出来,和调用本地方法一样的湿滑!

怎么实现的?如果你用过Mybatis,可以往Mybatis接口的实现类上思考,也许你能想到答案!


单独使用Feign实战

那么接下来,我们一起看一下,如果不在Spring Cloud框架下,Feign如何实现RPC调用!

本次实战案例的调用方:普通的SpringBoot程序。

调用地址:http://gg-user/user?id=123

gg-user是被调用的服务名

  • 1、引入Feign依赖
<!-- Feign核心 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>10.12</version>
</dependency>
<!-- Feign集成Netflix Ribbon -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-ribbon</artifactId>
    <version>10.12</version>
</dependency>
  • 2、定义接口UserService
import feign.Param;
import feign.RequestLine;

public interface UserService {
    @RequestLine("GET /user?id={id}")
    String getUserName(@Param("id") Integer id);
}

虽然不是SpringMVC的注解,但从@RequestLine注解能看出这是一个GET请求,路径是/user?id={id},{id}是占位符,通过 @Param("id")注解获取实际传入的id值。

  • 3、为UserService接口生成实现类

这里通过JavaConfig配置@Bean的方式实现注入:

@Configuration
public class FeignConfig {
    @Bean
    public UserService userService() {
        return Feign.builder()
                .client(RibbonClient.create())
                .target(UserService.class, "http://gg-user");
    }
}
  • 4、配置Ribbon的服务实例

这里配置到application.properties,因为不在Spring Cloud环境,所以没有注册中心,需要从配置文件中获取服务实例。

gg-user.ribbon.listOfServers=localhost:8081,localhost:8082

调用代码:

@Autowired
private UserService userService;

@GetMapping("/getUserName")
public String getUserName(@RequestParam("id") Integer id) {
    return userService.getUserName(id);
}

这样我们通过Feign就实现了非常优雅的RPC调用,最终GET请求url可能是:
http://localhost:8081/user?id=123
http://localhost:8082/user?id=123


Feign核心源码解读

Feign的核心代码写的非常好,非常值得我们学习和借鉴,所以我推荐大家学习下源码,本文只解读两个核心点作为抛转引玉。

  • Feign是如何动态生成的实现类?
return Feign.builder()
                .client(RibbonClient.create())
                .target(UserService.class, "http://gg-user");

通过这段代码,可以看出是通过target泛型方法生成的UserService实现类。

target会先build()出Feign的实现类ReflectiveFeign, 再调用ReflectiveFeign.newInstance方法,如下图:
Feign的target源码分析

ReflectiveFeign.newInstance方法内会调用Proxy.newProxyInstance生成动态代理类,如下图:
ReflectiveFeign.newInstance源码分析-动态代理

  • Feign是如何集成的Ribbon?

对于JDK动态代理,会在InvocationHandler里最终发起HTTP请求。而Feign把HTTP请求这部分做到了动态可插拔,封装成了Client接口,可以支持JDK 原生的 URLConnection、Apache HttpClient、OkHttp等等各类Client的实现。上面builder().client方法,就是用来指定Client的实现类。

这里指定的Client是:RibbonClient,它并不是HTTP调用的直接实现,从名子可以看出它主要整合Ribbon提供的是负载均衡功能。从实现上来看,它使用的是装饰器设计模式,就是为了在提供负载均衡功能的同时,还可以灵活指定其它Client,从而达到动态扩展的目的。
Feign通过RibbonClient集成Ribbon源码


Feign整体设计架构

Feign设计架构

通过上面的源码解读,我想你应该可以看懂架构图的上部和下部,Feign实际在设计上考虑了很多扩展功能,像Client、Log、Interceptor、Contract等等,非常灵活,非常强大,给了我们足够的扩展空间,它对所有的组件都提供了接口,如果对接口的实现类不满意,还可以基于Feign的接口来自定义实现。
所以,Spring Cloud正是通过Feign的扩展,将Feign完美整合到Spring Cloud框架中,形成了Spring Cloud OpenFeign


Spring Cloud OpenFeign实战

单独使用Feign的时候,我们还需要做一些配置,可一旦被Spring Cloud整合,那么一切就会变得非常非常简单,只需要加依赖+加注解

接下来,基于上文的Spring Cloud Alibaba工程环境,我们改造demo-a服务,将RestTemplate调用改成OpenFeign调用。

只需要三步就可以达到效果。

  • 第一步:引入 OpenFeign 组件

额外增加包spring-cloud-starter-openfeign,不用加版本,都在父工程定义了,上文已经说了版本。

<!-- Spring Cloud Open Feign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring Cloud Nacos Service Discovery 这是支持Nacos时加过的-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  • 第二步:定义远程API接口加@FeignClient

接口上额外增加@FeignClient注解,value=服务名
方法上换成SpringMVC注解,代替Feign注解

@FeignClient(value = "demo-b")
public interface UserService {
    @GetMapping("/user?id={id}")
    String getUserName(@RequestParam("id") Integer id);
}
  • 第三步:启动类加@EnableFeignClients

启动类上再增加注解@EnableFeignClients,用于扫描@FeignClient并生成动态代理类等

注意:如果UserService接口与启动类不在一个包package下,可以通过basePackages指定@FeignClient所在包路径.

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

通过以上三步操作,我们就达到了调用[远程服务方法]像调用[本地方法]一样! 调用代码如下:

@Autowired
private UserService userService;

@GetMapping("/getUserName")
public String getUserName(@RequestParam("id") Integer id) {
    return userService.getUserName(id);
}

Feign在实际项目的通常做法

在实际的Spring Cloud项目中,接口定义往往不是消费方来定义,通常做法是:

服务提供方负责定义、发布接口包,供消费方使用。

  • 好处:
  1. 一个服务可能被多个服务调用,可以避免每个消费方都定义接口
  2. 服务提供方最清楚接口如何调用
  • 对于消费方:
  1. 引入接口Jar包
  2. 增加@EnableFeignClients注解保证能扫描到Jar包

这样,消费方就可以很方便的直接调用了,你get了吗?


最后

通过本文,我们掌握了Feign的基本使用、核心原理,以及Spring Cloud Alibaba如何快速整合Feign,真的太简单了!你是不是觉得这样就够了?但在实际项目使用OpenFeign时,我们常常会遇到各种需求,需要用到它提供的扩展,例如日志分析、自定义统一拦截器、客户端组件配置、GZIP压缩等等,这也是我计划将在下文分享的内容,如果感觉不错,欢迎订阅本专栏,后面还有更多的【Spring Cloud Alibaba】实战知识陆续放出。

关注我 天罡gg 分享更多干货: https://blog.csdn.net/scm_2008
大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/406212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学生为什么要在CSDN写博客?

学生为什么要在CSDN写博客&#xff1f;引言写博客的好处构建知识体系提升写作能力扩展人脉为简历加分帮助他人为什么是CSDN如何写博客记录学习总结错误总结与展望引言 就目前来说&#xff0c;学生应该是使用各种博客最多的人&#xff0c;但却不是写博客的主体。在我看来&#…

软考-软件设计师 知识点整理(一篇就过了 建议收藏)

文章目录一 计算机组成CPU寻址方式校验码奇偶校验码&#xff08;只能检一位错&#xff0c;并且不能纠错&#xff09;循环冗余校验码CRC&#xff08;只能检错&#xff0c;不能纠错&#xff09;海明码计算机体系结构分类Flynn分类法&#xff08;理论存在&#xff1a;多指令单数据…

我用Python写了一个下载网站所有内容的软件,可见即可下,室友表示非常好用

Python 写一个下载网站内容的GUI工具&#xff0c;所有内容都能下载&#xff0c;真的太方便了&#xff01;前言本次要实现的功能效果展示代码实战获取数据GUI部分最后前言 哈喽大家好&#xff0c;我是轻松。 今天我们分享一个用Python写下载视频弹幕评论的代码。 之前自游写了…

VMware17虚拟机:下载和安装教程

签名&#xff1a;但行好事&#xff0c;莫问前程。 文章目录前言一、VMware虚拟机是什么&#xff1f;二、如何下载VMware虚拟机&#xff1f;1.打开VMware官方网站2.找到VMware17下载地址三、安装VMware17虚拟机1.双击exe文件2.点击下一步3.勾选许可协议&#xff0c;点击下一步4.…

Java单元测试介绍

文章目录单元测试单元测试基本介绍单元测试快速入门单元测试常用注解单元测试 单元测试基本介绍 单元测试: 单元测试就是针对最小的功能单元编写测试代码&#xff0c;Java程序最小的功能单元是方法&#xff0c;因此&#xff0c;单元测试就是针对Java方法的测试&#xff0c;进…

Error: EPERM: operation not permitted, mkdir ‘D:\software\nodejs\node_cache\_cacach两种解决办法

目录 报错情况&#xff1a;operation not permitted, mkdir ‘D:\software\nodejs\node_cache\_cacach 解决办法&#xff1a; 第一种&#xff1a;选择管理员身份运行命令行 第二种&#xff1a;node安装目录下设置users用户完全控制权限 报错情况&#xff1a;operation not …

电子工程师必须掌握的硬件测试仪器,你确定你都掌握了?

目录示波器示例1&#xff1a;测量示波器自带的标准方波信号输出表笔认识屏幕刻度认识波形上下/左右移动上下/左右刻度参数调整通道1的功能界面捕获信号设置Menu菜单触发方式触发电平Cursor按钮捕捉波形HLEP按钮参考资料频谱分析仪器信号发生器示波器 示例1&#xff1a;测量示波…

Spring Cloud Alibaba 微服务2,注册中心演变 + Nacos注册中心与配置中心

目录专栏导读一、什么是Nacos&#xff1f;二、注册中心演变及其设计思想1、RestTemplate调用远程服务2、通过Nginx维护服务列表&#xff08;upStream&#xff09;3、通过Nacos实现注册中心4、心跳版Nacos三、Nacos Discovery四、Nacos核心功能1、服务注册2、服务心跳3、服务同步…

【Jetpack】Jetpack 简介 ( 官方架构设计标准 | Jetpack 组成套件 | Jetpack架构 | Jetpack 的存在意义 | AndroidX 与 Jetpack 的关系 )

文章目录一、Google 官方推出的架构设计标准 Jetpack二、Jetpack 组成套件三、Jetpack 架构四、Jetpack 的存在意义1、提高开发效率2、最佳架构方案3、消除样本代码4、设备系统兼容性5、改善应用性能6、测试支持五、AndroidX 与 Jetpack 的关系一、Google 官方推出的架构设计标…

Termux安装完整版Linux(Ubuntu)详细步骤

一、Termux 1.Termux简介 Termux是 Android 平台上的一个终端模拟器&#xff0c;之所以称它为“模拟器”而非“虚拟机”&#xff0c;是因为它并非像 PC 端的 VirtualBox 等虚拟机软件那样&#xff0c;在宿主机中虚拟出一个完全独立且完整的系统环境&#xff0c;而只是提供一个…

MyBatis案例 | 使用映射配置文件实现CRUD操作——动态SQL优化条件查询

本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等&#xff0c;如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址&#xff1a;&#x1f525;JavaWeb Java入门篇&#xff1a; &#x1f525;Java基础学习篇 Java进阶学习篇&…

面试官:如何进行 JVM 调优(附真实案例)

前言 面试官&#xff1a;在工作中做过 JVM 调优吗&#xff1f;讲讲做过哪些 JVM 调优&#xff1f; 我一个QPS不到10的项目&#xff0c;上次问我缓存穿透缓存雪崩&#xff0c;这次问我 JVM 调优&#xff0c;我是真滴难。 不过大家别慌&#xff0c;热心的我给大家找来了几个满分…

一文学会IDEA中的Maven集成与创建(详细教程)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

‘conda‘不是内部或外部命令,也不是可运行的程序或批处理文件。

Anaconda环境搭建常见问题 conda不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 解决方案&#xff1a;配置环境变量 1.找到Anaconda Nvaigator单机右键 2.更多 3.打开文件所在位置 4.继续Anaconda Nvaigator单机右键&#xff0c;更多&#xff0c;选择文件…

Xilinx XDMA驱动代码分析及用法

Xilinx XDMA驱动代码分析及用法 先简单的介绍一下&#xff0c;赛灵思的XDMA的驱动是用于做什么的、他的主要功能就类似与网卡pcie接口的网卡驱动、用于控制主机与fpga设备进行pcie的通讯。通讯的主要方式是设备文件的读写&#xff0c;这里不清楚的同学可以看一下我上一篇文章。…

IDEA连接MySQL数据库并执行SQL语句使用数据

文章目录一、IDEA连接MySQL数据库&#xff08;一&#xff09;首先新建普通Java项目&#xff08;二&#xff09;连接数据库1、点击右侧DataBase2、点击加号&#xff0c;找到MySQL&#xff0c;添加数据库3、输入用户名和密码&#xff0c;点击**Test Connection**4、显示连接成功&…

深度分析| 数据防泄露技术再次“翻红”的思考与建议

此文章由天空卫士供稿 01、数据防泄露的定义 数据防泄露&#xff08;Data leakage prevention&#xff0c;DLP&#xff09;是指通过一定的技术和管理&#xff0c;防止组织内敏感数据或信息资产&#xff0c;违反安全约束而丧失组织控制、破坏数据机密性的策略和措施。数据防泄…

【云原生】裸金属架构之服务器安装VMWare ESXI虚拟化平台详细流程

??作者简介&#xff1a;大家好&#xff0c;我是&#xff0c;运维领域创作者&#xff0c;??阿里云ACE认证高级工程师?? 个人主页&#xff1a; ??支持我&#xff1a;点赞??收藏留言?? ??格言&#xff1a;你未必出类拔萃&#xff0c;但一定与众不同&#xff01;??…

[SSD4] 固态硬盘主控功能_SSD主控品牌

固态硬盘(Solid State Drives),简称SSD。它是一种电脑存储设备,由闪存(FLASH)、 闪存控制器、高速缓存(DRAM)组成。这是是固态硬盘的三个基本部件,对性能有关键影响。 了解一颗固态硬盘首先要从主控入手,主控对于固态硬盘的影响丝毫不亚于闪存。那么主控芯片对于固态硬盘…

来了!Python 官方发布了整套的中文PDF 文档(共27本)

1. 《Python中文指南》 学 Python 最好的学习资料永远是 Python 官方文档&#xff0c;可惜现在的官方文档大都是英文&#xff0c;虽然有中文的翻译版了&#xff0c;但是进度实在堪忧。 为了照顾英文不好的同学&#xff0c;我自己写了一份 面向零基础的朋友 的在线 Python 文档…