RPC:远程过程调用机制

目录

1、概念

2、RPC架构

2.1 RPC的四个核心组件

2.2 访问流程

3、关键概念

3.1 接口定义语言 (IDL - Interface Definition Language)

3.2 序列化与反序列化 (Serialization & Deserialization - Marshalling/Unmarshalling)

3.3 网络传输 (Transport)

3.4 服务发现 (Service Discovery) 

3.5 容错与重试 (Fault Tolerance & Retry):

3.6 安全 (Security)

3.7 异步与流式 (Asynchronous & Streaming)

4、RPC优缺点分析

5、常见RPC框架及其特点

6、现代趋势


1、概念

背景:分布式系统的组件分散在不同的虚拟机器上,需通过网络进行交互协作以完成共同的任务。

网络远程通信的基本原理:基于传输协议和网络IO来实现。其中传输协议有tcp、udp等,基于socket概念上扩展的协议。网络IO主要有bio、nio、aio三种方式。

RPC概念:远程过程调用的机制,不是一个具体的技术,RPC的核心目标,是让开发者调用远程机器上的函数(或方法)就像调用本地函数一样简单。开发者只关注于业务逻辑,而不是处理底层的Socket连接、数据序列化、反序列化、错误处理等繁琐细节。

2、RPC架构

2.1 RPC的四个核心组件

  • 客户端 (Client): 发起远程调用的应用程序。

  • 客户端存根 (Client Stub / Proxy):RPC 框架在客户端生成的代码(或动态代理),存放服务端的地址消息,将客户端的请求打包成网络消息(序列化),然后通过网络远程发送给服务方。

  • 服务端存根 (Server Stub / Skeleton): RPC 框架在服务端生成的代码(或动态代理),接收客户端发送过来的消息,将消息解包(反序列化),并调用本地的方法。

  • 服务端(Server):真正的服务提供者。

2.2 访问流程

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

RPC的目标就是将黄色部分的步骤封装起来。

java中的RPC框架:常见的有Hessian、gRPC、Dubbo等

3、关键概念

3.1 接口定义语言 (IDL - Interface Definition Language)

  • 核心概念: 一种与具体编程语言无关的语言,用于严格定义服务接口(方法、参数、返回值、数据结构、甚至异常)。

  • 作用:

    • 跨语言支持: 不同语言的客户端和服务器可以通过 IDL 文件生成各自语言的 Stub 和 Skeleton 代码。

    • 明确契约: 作为服务提供者和消费者之间的明确、可共享的合同。

    • 代码生成: RPC 框架提供编译器/工具,根据 IDL 文件自动生成客户端代理代码和服务器端骨架代码,减少手写网络通信代码的工作量和错误。

  • 常见 IDL: Protocol Buffers (.proto), Apache Thrift (.thrift), Avro IDL (.avdl), CORBA IDL, Web Services Description Language (WSDL - 用于 SOAP)。

  • 示例:Apache Thrift--Facebook的跨语言RPC框架,支持多种传输协议(TCP/HTTP等)。
// 定义服务 (calculator.thrift)
service Calculator {i32 add(1:i32 num1, 2:i32 num2),i32 subtract(1:i32 num1, 2:i32 num2)
}

Java使用步骤:

1> 用Thrift编译器生成代码:

thrift --gen java calculator.thrift

2> 实现接口:

public class CalculatorHandler implements Calculator.Iface {public int add(int num1, int num2) { return num1 + num2; }public int subtract(int num1, int num2) { return num1 - num2; }
}

3> 启动Thrift服务端,客户端通过Client类调用。

3.2 序列化与反序列化 (Serialization & Deserialization - Marshalling/Unmarshalling)

  • 核心概念: 将内存中的数据结构或对象转换为适合网络传输或存储的字节流的过程称为序列化。将接收到的字节流还原为内存中对象的过程称为反序列化。

  • 关键要求:

    • 高效性: 编码/解码速度快,产生的数据体积小(减少网络带宽和延迟)。

    • 跨语言性: 序列化后的数据能被不同语言编写的程序正确解析(IDL 是基础)。

    • 兼容性: 支持数据模式的演进(向前/向后兼容),允许服务接口和数据结构逐步升级而不破坏现有客户端或服务器。

    • 安全性: 防止恶意构造的数据导致反序列化漏洞。

  • 常见技术:

    • 二进制协议: Protocol Buffers (Protobuf), Apache Thrift (Binary), Apache Avro, MessagePack, Hessian。通常体积小、速度快。

    • 文本协议: JSON, XML。可读性好,但体积较大、解析较慢。常用于 RESTful API 和调试。

    • 语言内置: Java Serializable, Python Pickle。通常缺乏跨语言支持和良好的兼容性控制,不推荐用于生产环境 RPC。

  • 示例: Apache Thrift (Binary Protocol),支持多种传输协议(Binary/Compact/JSON)

// person.thrift
struct Person {1: string name,2: i32 id,3: list<string> emails
}
// 序列化
Person person = new Person("Alice", 123, Arrays.asList("alice@example.com"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
TBinaryProtocol protocol = new TBinaryProtocol(new TIOStreamTransport(baos));
person.write(protocol);  // 序列化
byte[] bytes = baos.toByteArray();// 反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
TBinaryProtocol inProto = new TBinaryProtocol(new TIOStreamTransport(bais));
Person decoded = new Person();
decoded.read(inProto);  // 反序列化
System.out.println(decoded.getName());  // 输出: Alice

3.3 网络传输 (Transport)

  • 核心概念: 负责在客户端 Stub 和服务器 Skeleton 之间可靠地传输序列化后的请求和响应数据。

  • 协议选择:

    • TCP: 最常用,提供可靠的、面向连接的字节流传输。是大多数 RPC 框架的基础。

    • HTTP/1.1: 基于 TCP,无状态,文本协议(虽然 Body 可以是二进制)。通用性强,易于通过防火墙和代理。但性能开销相对大,有队头阻塞问题。

    • HTTP/2: 解决了 HTTP/1.1 的队头阻塞问题,支持多路复用、头部压缩、服务器推送等特性,显著提升性能,已成为现代 RPC 框架(如 gRPC)的首选传输层。

    • HTTP/3 (QUIC): 基于 UDP,旨在进一步减少延迟,解决 TCP 队头阻塞问题,提供更好的移动网络体验,是未来趋势。

    • 自定义协议: 一些高性能框架(如 Dubbo)可能使用自定义的二进制协议直接在 TCP 上传输。

3.4 服务发现 (Service Discovery) 

  • 核心概念: 客户端如何找到它想调用的服务实例的网络位置(IP + Port)?尤其是在服务实例动态变化(扩缩容、故障重启)的分布式环境中。

  • 机制:

    • 静态配置: 直接在客户端配置服务端地址列表。简单但缺乏弹性,不适合动态环境。

    • 动态发现:

      • 注册中心 (Registry): 服务实例启动时向一个中心化的注册中心(如 ZooKeeper, etcd, Consul, Nacos, Eureka)注册自己的元数据(服务名、IP、Port、健康状态等)。客户端通过查询注册中心获取可用服务实例列表。

      • DNS: 通过 DNS SRV 记录或自定义域名解析来发现服务。更新可能不够实时。

  • 负载均衡 (Load Balancing): 通常与服务发现紧密结合。客户端从注册中心获取服务实例列表后,需要选择一个实例来发送请求。策略包括:轮询 (Round Robin)、随机 (Random)、加权轮询/随机、最少连接数 (Least Connections)、一致性哈希 (Consistent Hashing - 保证相同请求路由到相同实例,利于缓存)。

3.5 容错与重试 (Fault Tolerance & Retry):

  • 网络是不可靠的,服务实例可能临时故障。RPC 框架通常提供容错机制:

    • 超时 (Timeout):客户端设置一个等待响应的最大时间。防止因服务器挂起或网络问题导致客户端无限期等待,释放资源。

    • 重试 (Retry): 在遇到可重试错误(如网络瞬时故障、目标实例暂时不可用)时自动重试请求。需要谨慎设计(重试次数上限、重试间隔(固定、指数退避 - Exponential Backoff)、可重试错误类型判断),避免造成服务雪崩。

    • 熔断 (Circuit Breaking): 当某个服务失败率达到阈值时,暂时停止对其的请求(熔断器打开),直接返回失败或降级结果,给故障服务恢复的时间。过一段时间后尝试放行少量请求(半开状态),如果成功则关闭熔断器。

    • 降级 (Fallback): 当调用失败或熔断时,提供一种备选方案(如返回缓存数据、默认值、简化结果)以保证核心功能的可用性。

3.6 安全 (Security)

  • 认证 (Authentication): 验证调用者的身份(你是谁?)。常用方式:API Key/Secret, OAuth 2.0, JWT (JSON Web Tokens), mTLS (双向 TLS)。

  • 授权 (Authorization): 验证调用者是否有权限执行该操作(你能做什么?)。常用方式:基于角色 (RBAC) 或基于属性 (ABAC) 的访问控制。

  • 传输加密 (Encryption): 使用 TLS/SSL 对网络传输的数据进行加密,防止窃听和篡改。

3.7 异步与流式 (Asynchronous & Streaming)

  • 异步调用: 客户端发起调用后不阻塞等待结果,而是立即返回一个 Future/Promise 对象或注册一个回调函数。当结果准备好时,通过 Future/Promise 获取或调用回调函数通知客户端。提高资源利用率和吞吐量。

  • 流式 RPC: 允许在单个连接上建立双向的、持续的数据流。客户端可以发送一个请求流,服务器可以返回一个响应流,或者建立双向流。

    • 优势: 非常适合传输大量数据集(如文件上传/下载)、实时消息推送、聊天等场景。

    • 技术基础: HTTP/2 或 HTTP/3 的多路复用特性是实现高效流式 RPC 的关键(如 gRPC Stream)。

4、RPC优缺点分析

优点:

  • 开发效率高: 屏蔽了底层网络复杂性,开发者像调用本地函数一样开发分布式调用,降低心智负担,代码更简洁。

  • 抽象清晰: IDL 明确定义了服务接口,强类型约束,减少接口不一致的错误。

  • 跨语言能力: 基于 IDL 的代码生成天然支持多语言互操作,方便构建异构系统。

  • 性能潜力: 使用高效的二进制序列化协议(如 Protobuf, Thrift)和基于 TCP 的传输(或 HTTP/2),通常比基于文本的 RESTful API(尤其是 JSON over HTTP/1.1)具有更高的性能和更低的延迟。

  • 适合内部通信: 在微服务架构内部,服务之间需要频繁、高效、结构化的通信,RPC 是非常自然和高效的选择。

缺点:

  • 耦合性增加: 服务接口一旦通过 IDL 发布并生成代码,修改就需要同步更新客户端和服务端代码(虽然 Schema Evolution 可以缓解,但仍有成本)。相比 REST 的松散耦合(通过 URI 和 HTTP 动词),RPC 的接口耦合更紧密。

  • 调试复杂性: 跨进程、跨机器的调用使得调试比本地调用更困难。需要分布式追踪工具(如 Jaeger, Zipkin)来跟踪请求链路。

  • 技术栈绑定: 客户端和服务端需要支持相同的 RPC 框架和 IDL 生成器。虽然框架本身支持多语言,但选择了一个框架,整个系统通常就绑定在这个框架的生态上。

  • 防火墙穿透: RPC 框架通常使用非 HTTP 标准端口或自定义协议,可能在企业防火墙环境中遇到阻碍。基于 HTTP/2 的 RPC(如 gRPC)在这方面有优势。

  • 复杂性下沉: 虽然对业务开发者隐藏了网络复杂性,但 RPC 框架本身的实现、部署、监控、治理(服务发现、负载均衡、熔断限流)带来了额外的运维复杂性。需要一个成熟的微服务基础设施来支撑。

RPC vs REST:

特性RPCREST (Representational State Transfer)
核心范式动作/过程 (调用远程函数)资源 (操作资源的状态)
接口定义强契约 (IDL),严格定义方法签名弱契约,通过 URI 和 HTTP 动词隐含定义
耦合性较高 (客户端依赖特定服务接口)较低 (客户端只依赖资源 URI 和 HTTP 语义)
通信协议自定义协议或基于 HTTP/1.1/HTTP/2几乎总是基于 HTTP/1.1
数据格式高效二进制 (Protobuf, Thrift) 或文本文本为主 (JSON, XML)
性能通常更高 (二进制 + 高效协议)通常较低 (文本解析 + HTTP/1.1 开销)
适用场景内部服务间高效、结构化通信 (微服务)对公 API、需要松散耦合、更易调试/理解的场景
可发现性弱 (通常需要文档或 IDL) (利用 HTTP OPTIONS, HATEOAS 理念)
技术栈绑定强 (需要特定 RPC 框架支持)弱 (任何能发 HTTP 请求的语言/工具)
例子gRPC, Thrift, Dubbo 方法调用GET /users/123POST /orders

5、常见RPC框架及其特点

  • gRPC (Google): 基于 HTTP/2 和 Protocol Buffers (IDL & 序列化)。高性能,跨语言支持极好,原生支持流式调用。云原生领域事实标准。

  • Apache Dubbo (Alibaba): Java 生态高性能框架。提供丰富的服务治理能力(注册中心、配置中心、监控等),插件化扩展能力强。

  • Apache Thrift (Facebook): 跨语言 RPC 框架,有自己的 IDL 和多种序列化/传输协议选择。相对成熟稳定。

  • JSON-RPC / XML-RPC: 简单、轻量级、基于文本(JSON/XML),易于调试和集成,但性能通常不如二进制协议。

  • .NET Remoting / WCF: 微软 .NET 平台的 RPC 技术(WCF 更强大,支持多种通信协议和模式)。

6、现代趋势

  • 云原生集成: 与 Kubernetes、Service Mesh (Istio, Linkerd) 深度集成,利用其服务发现、负载均衡、安全、可观测性能力。

  • Protocol Buffers / gRPC 主导: 因其高效性、强类型契约和良好的跨语言支持,成为新项目的主流选择。

  • 异步非阻塞 & 流式优先: 高性能框架普遍采用 NIO/协程模型,并加强流式处理能力。

  • 可观测性内置: 指标、日志、追踪成为现代 RPC 框架的标配或易集成项。

  • 多协议支持: 一些框架(如 Dubbo)支持同时暴露多种协议(如 Dubbo, gRPC, REST)的端点,方便不同消费者接入。

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

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

相关文章

EPLAN 电气制图(六):电机正反转副勾主电路绘制

一、项目背景&#xff1a;为什么绘制电机正反转主电路&#xff1f; 在多功能天车系统中&#xff0c;电机正反转控制是核心功能之一。通过 EPLAN 绘制主电路&#xff0c;不仅能清晰展示电源分配、换相逻辑和线缆连接&#xff0c;还能为后续 PLC 控制设计奠定基础。本次以西门子设…

JAVA JVM对象的实现

jvm分配内存给对象的方式1. 内存分配的总体流程对象内存分配的主要步骤&#xff1a;类加载检查&#xff1a;确认类已加载、解析和初始化。内存分配&#xff1a;根据对象大小&#xff0c;从堆中划分内存空间。内存初始化&#xff1a;将分配的内存空间初始化为零值&#xff08;不…

CVE-2023-41990/CVE-2023-32434/CVE-2023-38606/CVE-2023-32435

CVE-2023-41990&#xff08;GitLab 命令注入漏洞&#xff09;漏洞原理CVE-2023-41990是GitLab CE/EE&#xff08;社区版/企业版&#xff09;中项目导出功能的一个命令注入漏洞。具体原理如下&#xff1a;①GitLab在导出项目时&#xff0c;会调用git命令生成项目存档&#xff08…

RAG实战指南 Day 8:PDF、Word和HTML文档解析实战

【RAG实战指南 Day 8】PDF、Word和HTML文档解析实战 开篇 欢迎来到"RAG实战指南"系列的第8天&#xff01;今天我们将深入探讨PDF、Word和HTML文档解析技术&#xff0c;这是构建企业级RAG系统的关键基础。在实际业务场景中&#xff0c;80%以上的知识都以这些文档格式…

【AXI】读重排序深度

我们以DDR4存储控制器为例&#xff0c;设计一个读重排序深度为3的具体场景&#xff0c;展示从设备如何利用3级队列优化访问效率&#xff1a;基础设定从设备类型&#xff1a;DDR4存储控制器&#xff08;支持4个存储体Bank0-Bank3&#xff09;读重排序深度&#xff1a;3&#xff…

牛马逃离北京(回归草原计划)

丰宁坝上草原自驾游攻略&#xff08;半虎线深度版&#xff09; &#x1f697; 路线&#xff1a;北京/承德 → 丰宁县城 → 半虎线 → 大滩镇&#xff08;2天1夜&#xff09; &#x1f3af; 核心玩法&#xff1a;免费草原、高山牧场、日落晚霞、牧群互动、星空烟花&#x1f33f;…

【前端】【Echarts】ECharts 词云图(WordCloud)教学详解

效果ECharts 词云图&#xff08;WordCloud&#xff09;教学详解 词云图是一种通过关键词的大小、颜色等视觉差异来展示文本数据中词频或权重的图表。它直观、形象&#xff0c;是数据分析和内容展示中的利器。 本文将带你从零开始&#xff0c;学习如何用 ECharts 的 WordCloud 插…

【arXiv 2025】新颖方法:基于快速傅里叶变换的高效自注意力,即插即用!

一、整体介绍 The FFT Strikes Again: An Efficient Alternative to Self-AttentionFFT再次出击&#xff1a;一种高效的自注意力替代方案图1&#xff1a;FFTNet整体流程&#xff0c;包括局部窗口处理&#xff08;STFT或小波变换&#xff0c;可选&#xff09;和全局FFT&#xff…

通过vue如何利用 Three 绘制 简单3D模型(源码案例)

目录 Three 介绍 创建基础3D场景 创建不同类型的3D模型 1. 球体 2. 圆柱体​​​​​​​ 3. 平面​​​​​​​ 加载外部3D模型 添加交互控制 创建可交互的3D场景 Three 介绍 Three.js是一个强大的JavaScript 3D库&#xff0c;可以轻松地在网页中创建3D图形。下面我…

云蝠智能 Voice Agent 落地展会邀约场景:重构会展行业的智能交互范式

一、行业痛点与 AI 破局在会展行业数字化转型的浪潮中&#xff0c;传统展会邀约模式面临多重挑战&#xff1a;人工外呼日均仅能处理 300-500 通电话&#xff0c;且无效号码占比高达 40% 以上&#xff0c;导致邀约效率低下。同时&#xff0c;个性化邀约话术设计依赖经验&#xf…

idea如何打开extract surround

在 IntelliJ IDEA 中&#xff0c;"Extract Surrounding"&#xff08;提取周围代码&#xff09;通常指 ​将一段代码提取到新的方法、变量或类中&#xff0c;但更常见的操作是 ​​"Surround With"&#xff08;用代码结构包围&#xff09;​。以下是两种场景…

window显示驱动开发—XR_BIAS 和 BltDXGI

Direct3D 运行时调用驱动程序的 BltDXGI 函数&#xff0c;以仅对XR_BIAS源资源执行以下操作&#xff1a;复制到也XR_BIAS的目标未修改的源数据的副本可接受点样本的拉伸旋转由于 XR_BIAS 不支持 MSAA) (多个示例抗锯齿&#xff0c;因此驱动程序不需要解析XR_BIAS资源。核心规则…

web网页开发,在线%ctf管理%系统,基于html,css,webform,asp.net mvc, sqlserver, mysql

webform,asp.net mvc。数据库支持mysql,sqlserver经验心得 每次我们写crud没啥技术含量&#xff0c;这没法让咱们进入大厂&#xff0c;刚好这次与客户沟通优化方案建议&#xff0c;咱们就把能加的帮他都加上去。一个ctf管理系统基本crud&#xff0c;并进行不同分层开发&#xf…

面试技术问题总结一

MySQL的几种锁机制一、从锁的粒度角度划分表级锁机制&#xff1a;它是对整张表进行锁定的一种锁。当一个事务对表执行写操作时&#xff0c;会获取写锁&#xff0c;在写锁持有期间&#xff0c;其他事务无法对该表进行读写操作&#xff1b;而当事务执行读操作时&#xff0c;会获取…

π0.5的KI改进版——知识隔离:让VLM在不受动作专家负反馈的同时,继续输出离散动作token,并根据反馈做微调(而非冻结VLM)

前言 过去的一个月(25年6.4-7.4)&#xff0c;我司「七月在线」具身长沙分部为冲刺一些为客户来现场看的演示项目&#xff0c;基本都用lerobot的那套框架 比如上周五(7.4日)晚上&#xff0c;通过上周五下午新采的第五波数据做『耳机线插入耳机孔』的任务&#xff0c;推理十次之…

Eigen中Isometry3d的使用详解和实战示例

Eigen::Isometry3d 是 Eigen 库中用于表示 三维空间中的刚性变换&#xff08;Rigid Transformation&#xff09; 的类&#xff0c;属于 Eigen::Transform 模板类的一个特化版本。它结合了 旋转和平移&#xff0c;广泛应用于机器人学、SLAM、三维几何计算等场景。一、核心定义 #…

《未来已来:当人类智慧遇上AI智能体》

在这个充满奇迹的时代,人类的智慧与科技的力量正以前所未有的速度交织在一起。 我们站在一个新时代的门槛上,一边是古老而深邃的自然规律,另一边是充满可能性的未来世界。 今天,就让我们一起走进这场关于人类智慧与AI智能体Kimi的对话,看看未来究竟会带给我们怎样的惊喜…

【三维生成】FlashDreamer:基于扩散模型的单目图像到3D场景

标题&#xff1a;<Enhancing Monocular 3D Scene Completion with Diffusion Model> 代码&#xff1a;https://github.com/CharlieSong1999/FlashDreamer 来源&#xff1a;澳大利亚国立大学 文章目录摘要一、前言二、相关工作2.1 场景重建2.2 扩散模型2.3 Vision languag…

CANFD记录仪设备在无人驾驶快递车的应用

随着物流行业的快速发展&#xff0c;无人驾驶快递车因其高效、低成本的优势&#xff0c;逐渐成为“最后一公里”配送的重要解决方案。然而&#xff0c;无人驾驶系统的稳定性和安全性高度依赖车辆总线数据的精准采集与分析。南金研CANFDlog4 4路记录仪凭借其多通道、高带宽、高可…

Kubernetes存储入门

目录 前言 一、Volume 的概念 二、Volume 的类型 常见的卷类型 Kubernetes 独有的卷类型 三、通过 emptyDir 共享数据 1. 编写 emptyDir 的 Deployment 文件 2. 部署该 Deployment 3. 查看部署结果 4. 登录 Pod 中的第一个容器 5. 登录 Pod 中的第二个容器查看/mnt下…