1.什么是远程调用
远程调用组件是SpringCloud核心组件之一。
远程调用(Remote Procedure Call, RPC)是指一个服务通过网络调用另一个服务的接口,以实现跨进程或跨机器的通信。在微服务架构中,服务之间通常通过远程调用来实现业务逻辑的协作。
2.SpringCloud远程调用的实现方式
2.1.RestTemplate
定义:RestTemplate 是 Spring 提供的一个同步 HTTP 客户端,用于调用 RESTful 服务
特点:
(1)简单易用,适合简单的 HTTP 调用
(2)支持与 Ribbon 集成,实现客户端负载均衡
示例:
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
public String callService() {
return restTemplate.getForObject("http://service-name/api", String.class);
}
2.2.Feign
描述:Feign 是一个声明式的 HTTP 客户端,通过接口和注解的方式定义远程调用。
特点:
(1)代码简洁,易于维护。
(1)支持与 Ribbon 和 Hystrix 集成,实现负载均衡和熔断。
示例:
@FeignClient(name = "service-name")
public interface ServiceClient {
@GetMapping("/api")
String callService();
}
@Autowired
private ServiceClient serviceClient;
public String callService() {
return serviceClient.callService();
}
2.3.OpenFeign
描述:OpenFeign 是 Feign 的社区增强版,支持更多功能和扩展
特点:
(1)支持 Spring Cloud LoadBalancer(替代 Ribbon)。
(2)支持响应式编程(Reactive)。
示例:
@FeignClient(name = "service-name")
public interface ServiceClient {
@GetMapping("/api")
String callService();
}
2.4.Spring Cloud Stream
描述:用于消息驱动的微服务,通过消息中间件(如 Kafka、RabbitMQ)实现服务间通信
特点:
(1)适合异步通信场景。
(2)解耦服务间的直接依赖。
2.5.gRPC
描述:gRPC 是一个高性能的 RPC 框架,基于 HTTP/2 和 Protocol Buffers
特点:
(1)性能高,适合对性能要求较高的场景。
(2)支持多语言。
3.SpringCloud远程调用的核心特征
(1)负载均衡
- Spring Cloud 通过集成 Ribbon 或 Spring Cloud LoadBalancer,实现了客户端负载均衡
- 服务消费者可以从多个服务提供者实例中选择一个进行调用
(2)熔断与降级
-
通过集成 Hystrix 或 Spring Cloud CircuitBreaker,实现了服务的熔断和降级。
-
当服务调用失败或超时时,可以快速失败或返回降级结果,避免雪崩效应。
(3)服务发现
-
通过集成注册中心(如 Eureka、Nacos),实现了服务的动态发现。
-
服务消费者无需硬编码服务提供者的地址,而是从注册中心获取可用的服务实例。
(4)声明式调用
-
Feign 和 OpenFeign 提供了声明式的远程调用方式,通过接口和注解定义调用逻辑,代码简洁易读。
4.SpringCloud远程调用的优势
(1)简化开发:通过声明式调用(如 Feign)和自动化配置,开发者可以快速实现服务间通信。
(2)提高可用性:通过负载均衡、熔断和降级机制,确保服务的高可用性。
(3)动态扩展:结合注册中心,支持服务的动态发现和扩展。
(4)性能优化:支持多种通信协议(如 HTTP、gRPC),满足不同场景的性能需求。
5.实际应用经验
-
在项目中,我使用 Feign 实现了服务间的远程调用,结合 Ribbon 实现了负载均衡,并通过 Hystrix 实现了熔断和降级。
-
通过 Nacos 作为注册中心,实现了服务的动态发现和调用。
-
在高并发场景下,使用 gRPC 替代 HTTP,显著提升了服务调用的性能。
6.进阶
6.1.HTTP与RPC的区别
- 严格来讲,HTTP 和RPC不是一个层面上的东西,可以说RPC包含HTTP,也可以说RPC在HTTP之上
- HTTP(Hypertex Transfer Protocol)是一种应用层协议,主要强调的是网络通信
- RPC(Remote Procedure Call,远程过程调用)是一种用于分布式系统之间通信的协议,强调的是服务之间的远程会调用
- 一些RPC框架,比如gRPC,底层传输协议其实也是用的HTTP2,包括Dubbo3,也兼容了gRPC,使用了HTTO2作为传输层的一层协议
- 在微服务体系里,基于HTTP风格的远程调用通常使用框架如Feign来实现,基于RPC的远程调用通常使用框架如Dubbo来实现
如果硬要说区别的话:
6.2.Feign和Dubbo的区别
这两个才是适合比较的东西:
要注意的时,Feign和Dubbo并不是互斥的关系。实际上,Dubbo可以使用HTTP协议作为通信方式,而Feign也可以继承RPC协议进行远程调用。选择使用哪种远程调用方式取决于具体的业务需求和技术栈的选择
6.3.Feign和OpenFeign的区别
来源与维护:
- Feign 最初由 Netflix 开发,是 Netflix OSS 的一部分,后来被 Spring Cloud 集成到其生态系统中。它是一个独立的库,主要用于声明式的 REST 客户端开发。
- OpenFeign 是 Feign 的社区维护版本,由 OpenFeign 社区主导开发。它是对 Feign 的增强和扩展,提供了更多的功能和更好的兼容性。
功能增强:
Feign:功能相对基础,支持声明式接口、负载均衡(与 Ribbon 集成)、请求拦截等。
OpenFeign:在Feign的基础上增加了很多功能:
- 更好的 Spring 生态集成(如 Spring MVC 注解支持)
- 支持 Spring Cloud LoadBalancer(替代 Ribbon)
- 更灵活的扩展机制。
- 支持响应式编程(Reactive)
- 提供更丰富的注解和配置选项
与 Spring Cloud 的集成:
- 早期 Spring Cloud 使用的是 Netflix Feign,但 Netflix 已经停止维护 Feign,因此 Spring Cloud 逐渐转向 OpenFeign。
- 目前 Spring Cloud 官方推荐使用 OpenFeign,它与 Spring Cloud 的集成更加紧密,支持最新的 Spring Cloud 特性(如 Spring Cloud LoadBalancer)
依赖关系:
Feign:适用于早期的 Spring Cloud 项目,或者不需要最新特性的场景
OpenFeign:适用于新项目或需要更多功能和更好兼容性的场景,尤其与 Spring Cloud 2020.x 及以上版本集成时
总结:
同:
- Feign和OpenFeign作用一样,都是进行远程调用的组件。
- 里面都内置了Ribbon。
- 都是加在消费端的注解,让消费端可以调用其他生产者的服务。
异:
- 依赖不同,一个是spring-cloud-starter-feign,一个是spring-cloud-starter-openfeign。
- 使用方式不同,Feign直接加在接口上并且不支持SpringBoot注解。OpenFeign支持@RequestMapping("/demo/test")这种注解。
6.4.Feign怎么做负载均衡
在Feign中,负载均衡时通过继承Ribbon来实现的
Ribbon在发起请求前,会从“服务中心”获取服务列表(清单),然后按照一定的负载均衡策略去发起请求,从而实现客户端的负载均衡。Ribbon本身也维护者“服务提供者”清单的有效性。如果它发现“服务提供者”不可用,则会重新从“服务中心”获取有效的“服务提供者”清单来及时更新
6.5.为什么Feign第一次调用耗时很长
主要原因是由于Ribbon的懒加载机制,当第一次调用发生时,Feign会触发Ribbon的加载过程,包括从服务注册中心获取服务列表,建立连接池等操作,这个加载过程会增加首次调用的耗时
ribbon:
eager-load:
enabled: true
clients: service-1
那怎么解决这个问题呢?
可以在应用启动时预热Feign客户端,自动触发一次无关紧要的调用,来提前加载Ribbon和其他相关组件。这样,就相当于提前进行了一次调用/
6.6.Feign怎么实现认证传递
比较常见的一个做法是,使用拦截器传递认证信息。可以通过实现Requestlnterceptor接口来定义拦截器,在拦截器里,把认证信息添加到请求头中,然后将其注册到Feign配置中
代码示例:
@Configuration
public class FeignClientConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
// 添加认证信息到请求头中
template.header("Authorization", "Bearer " + getToken());
}
};
}
private String getToken() {
// 获取认证信息的逻辑,可以从SecurityContext或其他地方获取
// 返回认证信息的字符串形式
return "your_token";
}
}
6.7.服务端负载均衡和客户端负载均衡的区别
服务端:
客户端:
客户端负载均衡器的实现原理时通过注册中心,如Nacos,将可用的服务列表拉取到本地(客户端),再通过客户端负载均衡器(设置的负载均衡策略)获取到某个服务器端具体ip和端口,然后通过HTTP框架请求服务并得到结果
7.关联文章
如此等等的资料我都已经整理到了思维导图中,本篇属于SpringCloud篇,有需要的可以去看一下,喜欢的就留个三连再走吧~
SpringCloud:https://blog.youkuaiyun.com/TLOVEYOUTOO/article/details/145532603?spm=1001.2014.3001.5502
Spring全家桶:
https://blog.youkuaiyun.com/TLOVEYOUTOO/article/details/145532922?spm=1001.2014.3001.5502