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

article/2025/9/2 10:07:00

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 {@Beanpublic 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://chatgpt.dhexx.cn/article/Y8emsmbJ.shtml

相关文章

聊聊 Feign 的实现原理

What is Feign Feign 是⼀个 HTTP 请求的轻量级客户端框架。通过 接口 注解的方式发起 HTTP 请求调用&#xff0c;面向接口编程&#xff0c;而不是像 Java 中通过封装 HTTP 请求报文的方式直接调用。服务消费方拿到服务提供方的接⼝&#xff0c;然后像调⽤本地接⼝⽅法⼀样去…

简单谈谈Feign

简单谈谈Feign 文章目录 简单谈谈Feign前言Feign属于RPC嘛&#xff1f; 原理简单图解原理简述Feign.Build动态代理工厂InvocationHandlerFactory动态代理类FeignInvocationHandler方法处理器MethodHandler 总结 本文只是简单粗略的分析一下feign的源码与过程原理 前言 Feign是…

Feign 原理 (图解)

疯狂创客圈 经典图书 &#xff1a; 《Netty Zookeeper Redis 高并发实战》 面试必备 面试必备 面试必备 【博客园总入口 】 疯狂创客圈 经典图书 &#xff1a; 《SpringCloud、Nginx高并发核心编程》 大厂必备 大厂必备 大厂必备 【博客园总入口 】 入大厂涨工资 必备的 …

Feign详解与实例

基本介绍 Feign是一种负载均衡的HTTP客户端, 使用Feign调用API就像调用本地方法一样&#xff0c;从避免了调用目标微服务时&#xff0c;需要不断的解析/封装json 数据的繁琐。Feign集成了Ribbon。Ribboneureka是面向微服务编程&#xff0c;而Feign是面向接口编程。 Fegin是一个…

Feign使用和原理的总结

官方参考 https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/ 使用 引入依赖 <properties><java.version>1.8</java.version><spring-cloud.version>2021.0.1</spring-cloud.version></properties><depen…

Feign的介绍

Feign是springcloud里面的一个功能组件&#xff0c;那么它是实现一个什么功能呢&#xff1f; 首先我们可以先从字面意思上去理解一下它&#xff0c;Feign&#xff0c;英文翻译过来就是伪装的意思&#xff0c;实际上它的功能也是和伪装相关的&#xff0c;在我们之前在客户端配置…

FeignClient原理解读

FeignClient原理解读 简介源码解读feign负载ribbon源码解读eurake的ribbon原理是&#xff1a;调度原理&#xff1a; 笔记参考文献 简介 这一章节主要介绍feignClient的地址如何来&#xff0c;如何从feign Server注册中心寻址和调用。 源码解读 在解读源码之前&#xff0c;建…

Spring Cloud-Feign设计原理

什么是Feign&#xff1f; Feign 的英文表意为“假装&#xff0c;伪装&#xff0c;变形”&#xff0c; 是一个http请求调用的轻量级框架&#xff0c;可以以Java接口注解的方式调用Http请求&#xff0c;而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解&am…

再学一下Feign的原理

简介 Feign是Spring Cloud Netflix组件中的一个轻量级Restful的HTTP服务客户端&#xff0c;它简化了服务间调用的方式。 Feign是一个声明式的web service客户端.它的出现使开发web service客户端变得更简单.使用Feign只需要创建一个接口加上对应的注解, 比如FeignClient注解。…

Feign的底层原理

Feign的底层原理 1 EnableFeignClients2 根据接口上的注解创建RequestTemplate3 发送请求 1 EnableFeignClients 这个注解标注在springboot的启动类上,作用是开启feign接口扫描 FeignClientsRegistrar.registerFeignClients()扫描被FeignClient标识的接口生成代理类 public vo…

深入理解Feign之源码解析

转载请标明出处&#xff1a; https://blog.csdn.net/forezp/article/details/73480304 本文出自方志朋的博客 出自方志朋的博客 个人博客纯净版&#xff1a;https://www.fangzhipeng.com/springcloud/2017/08/11/sc-feign-raw.html 什么是Feign Feign是受到Retrofit&#xff…

SpringCloud 中Feign原理(图解)

1 SpringCloud 中Feign原理 1.1 Feign简介 Feign是Netflix公司开源的轻量级rest客户端&#xff0c;使用Feign可以非常方便的实现Http 客户端。Spring Cloud引入Feign并且集成了Ribbon实现客户端负载均衡调用。 1.2 Feign远程调用的基本流程 Feign远程调用&#xff0c;核心就是…

Feign(简介和使用)

1. Feign介绍 通过RestTemplate调用其它服务的API时&#xff0c;所需要的参数须在请求的URL中进行拼接&#xff0c;如果参数少的话或许我们还可以忍受&#xff0c;一旦有多个参数的话&#xff0c;这时拼接请求字符串就会效率低下 Feign是一个声明式的Web Service客户端&#…

什么是Feign?

服务间调用介绍 现有的服务调用方式 利用拼接的方式。 虽然上面有的用不错就很好了 Feign解决了什么问题 Feign的调用方式 Feign体系架构解析-武装到牙齿 上一节我们了解了feign的主要功能&#xff0c;它就像一个自拍杆一样&#xff0c;方便了Eureka的远程调用。可是怎么看…

Feign 的实现原理

Feign 实现原理 Feign是申明式的 HTTP 客户端。代码中创建一个接口并加上FeingClient 注解即可使用。其底层封装了 HTTP 客户端构建并发送的复杂逻辑。同时也可以整合注册中心及 Ribbon 为其提供负载均衡能力&#xff1b;通过整合 Histrix/sentinal 实现熔断限流功能。本期主要…

OpenFeign的实现原理(附Feign和OpenFeign的区别)

目录 问题现象&#xff1a; 问题分析&#xff1a; 拓展&#xff1a; 1、Feign&#xff1a; 2、OpenFeign&#xff1a; 问题现象&#xff1a; 最近在复习SpringCloud的时候看到一个面试题&#xff1a; OpenFeign的实现原理&#xff1f; 问题分析&#xff1a; OpenFeign是Sp…

Feign原理

是一个HTTP请求调用轻量级框架&#xff0c;可以以Java接口注解的方式调用HTTP请求&#xff0c;而不用像Java中通过封装HTTP请求报文的方式直接调用。 Feign解决了什么问题 在服务调用的场景中&#xff0c;我们经常调用基于HTTP协议的服务&#xff0c;而我们经常使用到的框架可…

Feign的使用及原理剖析

feign使用及原理剖析 一、简介 Feign是一个http请求调用的轻量级框架&#xff0c;可以以Java接口注解的方式调用Http请求。Feign通过处理注解&#xff0c;将请求模板化&#xff0c;当实际调用的时候&#xff0c;传入参数&#xff0c;根据参数再应用到请求上&#xff0c;进而转…

Feign基本使用(超详细)

目录 一、Feign概述 二、Feign入门 1.创建服务提供者(provider) 2.创建feign接口 3、创建服务消费者(consumer) 三、Feign 原理 四、Feign优化 1、开启feign日志 2、feign超时问题 3、http连接池 4、gzip压缩 前言 当我们通过RestTemplate调用其它服务的API时&#xff0c;所…

简单理解Feign的原理与使用

文章目录 SpringCloud 总架构图一、简介1.1、负载均衡的概念2.2、Feign概念 二、入门案例2.1、导入依赖2.2、Feign的客户端2.3、调用Feign2.4、开启Feign功能2.5、启动测试2.6、Feign实现原理简单分析 三、负载均衡(Ribbon)四、熔断器支持五、请求压缩和响应压缩六、配置日志级…