微服务7:通信之RPC

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 微服务7:通信之RPC

1 什么是RPC通信

RPC:Remote Procedure Call Protocol,指的是远程过程调用协议,一般使用在分布式业务或者微服务架构风格中。

即一个节点通过网络调用的方式来请求另一个节点提供的服务的过程,也可以简单的理解为client访问server上提供的函数(像调用本地函数一样,去调用一个远端服务)。

2 RPC通信详解

2.1 RCP角色和职能

在RPC框架中主要有三个角色:Provider、Consumer和Registry。如下图所示:

image.png

 

节点角色说明,这边看起来,跟其他的服务注册与发现框架原理差不多(如  Eureka、Consul):

Service(provider): 暴露服务的服务提供方。

Client(consumer): 调用远程服务的服务消费方。

Registry: 服务注册与发现的注册中心。

2.2 RPC调用流程

RPC(Remote Procedure Call)远程过程调用,即一个节点通过网络调用的方式来请求另一个节点提供的服务的过程,也可以简单的理解为client访问server上提供的函数。

他的基本调用流程如下:

image.png

上面是一次完整的RPC调用流程(这边指的是同步调用情况下),步骤顺序如下:

  1. 客户端(client)以本地调用方式(即以接口的方式)调用服务;
  2. 客户端存根(client stub)接收到调用后,负责将方法、参数等组装成能够进行网络传输的消息体(将消息体对象序列化为二进制 byte[]);
  3. 客户端通过sockets将消息发送到服务端;
  4. 服务端存根( server stub)收到消息后进行解码(将消息对象反序列化);
  5. 服务端存根( server stub)根据解码结果调用本地的服务;
  6. 本地服务执行并将结果返回给服务端存根( server stub);
  7. 服务端存根( server stub)将返回结果打包成消息(将结果消息对象序列化);
  8. 服务端(server)通过sockets将消息发送到客户端;
  9. 客户端存根(client stub)接收到结果消息,并进行解码(将结果消息反序列化);
  10. 客户端(client)得到最终结果。

RPC的目标是要把2、3、4、7、8、9这些步骤都封装起来。

无论是何种类型的数据,最终都需要转换成二进制流在网络上进行传输,数据的发送方需要将对象转换为二进制流,而数据的接收方则需要把二进制流再恢复为对象。

2.3 多服务RPC通信模型

理解对服务的调用和RPC模式的结果返回,注意箭头的指向的区别。

image.png

2.4 RPC通信使用到的技术

1、动态代理(Spring中重点了解下)

生成 client stub和server stub需要用到 Java 动态代理技术 ,我们可以使用JDK原生的动态代理机制,可以使用一些开源字节码工具框架 如:CgLib、Javassist等。

2、序列化

序列化:将Java对象转换成byte[]的过程,也就是编码的过程;

反序列化:将byte[]转换成Java对象的过程;

3、NIO

当前很多RPC框架都直接基于netty这一IO通信框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推荐使用 Netty 作为底层通信框架。

4、服务注册中心

可选技术:Redis 、Zookeeper,

一般的RPC框架会接入注册中心来进行注册与发现的管理,比如Dubb与Zookeeper 的完美结合。

所以实现RPC调用过程,结构分为三部分:client、grpc、server。

2.5 RPC通信与普通函数调用的区别

虽然RPC可以简单的理解为client 去调用server 中的函数。但是RPC通信和直接的函数调用还是有很大的区别的:

内容项

RPC调用

本地调用

函数寻址

IP端口路由(NamingService + LoadBalancer)+函数路由

内存指针

传递数据

序列化后的数据流

内存对象

调用方异常处理

timeout、retry、curcuit breaker

抛出Exception / 函数返回固定异常标识的数据

被调用方异常处理

认证鉴权、过载保护

入参检查 / 执行异常捕获和处理

问题定位

分布式Trace、监控、日志中心

日志记录 / 断点调试跟踪

性能优化

连接池、多路复用、线程池、轻量级线程、non-block IO 等

编译器优化(inline等)

这里可以看出rpc比函数调用复杂的多,比如:

  • 函数寻址:你怎样调到你想要的哪个函数?在本地调用中其实就是一个函数指针,但是在RPC场景下,你要找到这个函数其实非常复杂,一个服务一般有多个下游实例,首先要选择一个下游实例,一般这个是由NamingService+LB来实现,到达对应的实例后,服务端还要解析请求体,找到函数名,然后做函数路由。
  • 数据传递:在本地调用过程中其实就是传递一个指针或者值,在RPC场景下其实是通过网络传递的,网络上需要传递一个内存对象序列化之后的一个二进制网络数据流,response回来的时候也需要经过一个反序列化的过程。
  • 异常处理:本地调用的情况下,无非就是判断下这个函数的返回值或者有没有抛一些异常,但是在RPC场景下就很复杂,比如网络拥塞了,服务端处理慢了或者超时,还有很多异常的情况,所以我们要做很多系统容错的事情,比如:超时、重试等策略来解决这些问题。本地调用的时候我只需要检查参数是否合法,但是在RPC的场景下我们要做一些类似认证鉴权,过载保护等策略,避免流量过大将server打挂。
  • 问题定位:本地调用方法很多,比如:断点调试,打本地日志。但是在RPC场景下,这些方法其实是行不通的,我们需要分布式tracing、监控和分布式日志中心来帮助我们定位问题。
  • 性能优化:本地调用其实我们不用关心太多,因为编译器会帮我们做一些列的优化,但是在RPC的场景下,就需要我们自己优化通信效率,常用的优化手段比如:连接池、多路复用、线程池等等很多方法,这些方法实现起来都非常的复杂。现在大家应该能理解RPC场景是非常复杂的

正因为有如此的复杂性,所以我们需要一个RPC框架来处理这些复杂的事情,让RPC看起来就像本地调用一样简单。  

2.6 RPC 框架调用流分析

2.6.1 RPC框架功能(简单版本)

 

image.png

实现的过程:

  • client初始化一个channel,监听NamingService,从服务名字中解析出来服务真正的上游实例地址
  • 客户端将请求的的数据进行序列化
  • 上游可能多个实例,需要LB去选择一个下游的IP+Port,选出来之后需要和上游实例建立连接和发送请求
  • 建立连接之后发送请求
  • 服务端接着接受连接和接受数据,收到数据之后将二进制数据反序列化为一个内存对象request
  • 然后再调用server的响应方法进行处理
  • 服务端通过sockets将消息发送到客户端;
  • 客户端接收到结果消息,并进行解码(将结果消息反序列化)

2.6.2 RPC框架功能(复杂版本)

image.png

有些RPC框架不只是处理通信相关的工作(如数据的序列化和反序列化,协议的解析/打包,数据的压缩解压缩,数据的加密和解密),还可以做很多微服务治理的工作。

比如Dubbo支持对服务的治理,包括 服务注册与发现、故障注入、超时重试、负载均衡、连接管理和健康检查等。除此之外,服务端还有认证鉴权、并发流量限制、函数路由、协议适配和参数校验等等复杂的策略。

所以一个成熟的RPC框架也可以是一个非常复杂全面的分布式系统,在一定程度上协助工程进行微服务建设。

2.7 主流RPC 框架对比

对比项

Dubbo

gRPC

brpc

Thrift

公司

Ali

Google

Baidu

FaceBook

通讯协议

tcp/http

http2

多种协议

tcp/http

序列化协议

可扩展

protobuf

protobuf/json/mcpack

可扩展

开发语言

Java

跨语言

C++ / Java

跨语言

主要特点

服务治理、扩展性

跨语言、性能

高性能、扩展性

跨语言

github star

36.9K

33.5K

12.9K

8.9K

2.8 与RESTful API 的区别

RPC 主要用于公司内部的服务调用,性能消耗低,传输效率高,实现复杂。

HTTP 主要用于对外的异构环境,浏览器接口调用,App 接口调用,第三方接口调用等。

RPC 使用场景(大型的网站,内部子系统较多、接口非常多的情况下适合使用 RPC):

  • 长链接。不必每次通信都要像 HTTP 一样去 3 次握手,减少了网络开销。
  • 注册发布机制。RPC 框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。
  • 安全性,没有暴露资源操作。
  • 微服务支持。就是最近流行的服务化架构、服务化治理,RPC 框架是一个强力的支撑。

3 总结

通过本篇我们详细学习了RPC的概念和原理,以及它能够提供的能力。也对目前业内主流的RPC的框架有了一定的了解。后面一篇我们以Dobbo为例子,来学习下怎么使用RPC框架来进行服务之间的通信。

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
1月前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
58 2
|
3月前
|
消息中间件 监控 网络协议
构建高效微服务通信:选择合适的通信方式
构建高效微服务通信:选择合适的通信方式
|
3月前
|
Dubbo Java 应用服务中间件
💥Spring Cloud Dubbo火爆来袭!微服务通信的终极利器,你知道它有多强大吗?🔥
【8月更文挑战第29天】随着信息技术的发展,微服务架构成为企业应用开发的主流模式,而高效的微服务通信至关重要。Spring Cloud Dubbo通过整合Dubbo与Spring Cloud的优势,提供高性能RPC通信及丰富的生态支持,包括服务注册与发现、负载均衡和容错机制等,简化了服务调用管理并支持多种通信协议,提升了系统的可伸缩性和稳定性,成为微服务通信领域的优选方案。开发者仅需关注业务逻辑,而无需过多关心底层通信细节,使得Spring Cloud Dubbo在未来微服务开发中将更加受到青睐。
86 0
|
2月前
|
Dubbo 应用服务中间件 Apache
Star 4w+,Apache Dubbo 3.3 全新发布,Triple X 领衔,开启微服务通信新时代
在 Apache Dubbo 突破 4w Star 之际,Apache Dubbo 团队正式宣布,Dubbo 3.3 正式发布!作为全球领先的开源微服务框架,Dubbo 一直致力于为开发者提供高性能、可扩展且灵活的分布式服务解决方案。此次发布的 Dubbo 3.3,通过 Triple X 的全新升级,突破了以往局限,实现了对南北向与东西向流量的全面支持,并提升了对云原生架构的友好性。
141 7
|
2月前
|
存储 安全 API
微服务之间的安全通信
在微服务架构中,服务之间的通信是系统的核心部分。然而,由于服务的分布式和独立性,确保它们之间的通信安全至关重要。
49 3
|
2月前
|
存储 安全 API
微服务之间的安全通信
在微服务架构中,服务之间的通信是系统的核心部分。然而,由于服务的分布式和独立性,确保它们之间的通信安全至关重要。如果没有适当的安全机制,微服务系统可能会暴露在各种网络攻击和安全漏洞中。
42 4
|
2月前
|
存储 搜索推荐 数据库
MarkLogic在微服务架构中的应用:提供服务间通信和数据共享的机制
随着微服务架构的发展,服务间通信和数据共享成为关键挑战。本文介绍MarkLogic数据库在微服务架构中的应用,阐述其多模型支持、索引搜索、事务处理及高可用性等优势,以及如何利用MarkLogic实现数据共享、服务间通信、事件驱动架构和数据分析,提升系统的可伸缩性和可靠性。
45 5
|
3月前
|
消息中间件 Java API
解密微服务架构:如何在Java中实现高效的服务通信
微服务架构作为一种现代软件开发模式,通过将应用拆分成多个独立的服务,提升了系统的灵活性和扩展性。然而,实现微服务之间的高效通信仍然是许多开发者面临的挑战。本文将探讨在Java环境中实现微服务架构时,如何使用不同的通信机制来优化服务之间的交互,包括同步和异步通信的方法,以及相关的最佳实践。
|
3月前
|
Java 数据库连接 Spring
当在线购物遇上数据危机:Hibernate 事务管理如何力挽狂澜,确保每一次交易都万无一失?
【8月更文挑战第31天】数据一致性和事务管理对任何企业级应用至关重要,尤其是在使用 Hibernate 时。本文通过在线购物系统的具体案例,介绍了正确管理事务的重要性。以 `Product` 和 `Order` 实体为例,阐述了如何通过编程式或声明式事务管理(如 Java 代码示例中的 `@Transactional` 注解)来确保数据一致性。正确配置事务能显著提升应用质量和系统稳定性。
36 0
|
3月前
|
JSON API 数据格式
揭秘微服务间沟通的神秘语言!Ruby如何化身“信使”,让服务间通信畅通无阻?
【8月更文挑战第31天】随着应用程序规模的不断扩大,微服务架构因高度模块化、可扩展性和可维护性成为现代软件开发的首选。本文通过示例代码展示如何使用 Ruby 实现微服务间的通信,重点介绍 RESTful API 的应用。首先,通过安装 HTTParty 库简化 HTTP 请求处理;然后创建微服务客户端,演示如何调用用户服务的 API 并获取用户信息;最后,介绍如何解析 JSON 响应,使数据处理更加便捷。这种方式不仅简单高效,还能满足大多数微服务架构下的通信需求。
44 0
下一篇
无影云桌面