一、序言:为什么我们需要RPC?

        在单体应用时代,函数调用是进程内的简单操作。但随着业务规模扩大,系统被拆分为多个独立服务(如订单服务、支付服务),服务间通信成为刚需。早期开发者常使用HTTP+JSON手动实现通信,但这带来了显著问题:网络细节侵入业务代码(如处理超时、重试)、性能开销大(文本解析慢)、类型安全缺失(JSON弱类型易出错)。RPC框架应运而生——它通过抽象化远程调用,将开发者从底层网络编程中解放出来。

        RPC的核心价值在于透明性:调用远程方法如同本地调用,框架自动处理序列化、网络传输、错误恢复等。例如,在电商系统中,订单服务调用“支付服务.扣款()”时,无需关心支付服务部署在哪台机器、网络是否稳定。主流框架如gRPC、Dubbo、Thrift已验证了其工业级可靠性,成为微服务架构的“神经系统”。本文将带你穿透表象,理解RPC如何让分布式系统“像单机一样简单”。

二、原理:整体设计框架与核心组件

RPC的本质是模拟本地调用的远程通信,其设计围绕“隐藏网络复杂性”展开。整体框架可分为五大核心组件,形成一条完整的调用链路:

  1. 客户端存根(Client Stub)
    • 作用:作为本地服务的代理,拦截开发者对远程方法的调用。它将方法名、参数等封装为请求消息,并触发序列化与网络发送。
    • 关键细节:对开发者完全透明——你调用的paymentService.deduct(amount)实际是存根的代理方法,而非真实服务。
  1. 序列化层(Serializer)

    • 作用:将对象(如Java对象、Go结构体)转换为字节流(序列化),或反向转换(反序列化)。
    • 关键细节:选择高效协议(如Protocol Buffers、Thrift Binary)可减少50%+网络流量。例如gRPC默认使用Protobuf,比JSON快3-10倍。
  2. 网络传输层(Transport)

    • 作用:通过TCP/HTTP2等协议传输字节流,处理连接管理、超时、重试。
    • 关键细节:现代框架(如gRPC)采用多路复用(HTTP/2)避免队头阻塞,单连接承载多请求,显著提升吞吐量。
  3. 服务端骨架(Server Skeleton)

    • 作用:接收字节流后反序列化,解析方法名和参数,将请求路由到真实服务实现
    • 关键细节:通过反射或代码生成调用目标方法(如Java的Method.invoke()),并将结果封装为响应消息。
  4. 服务注册与发现(Registry,可选但关键)

    • 作用:在动态环境中(如K8s集群),管理服务实例地址。客户端通过注册中心(如ZooKeeper、Nacos)获取可用服务列表。
    • 关键细节:实现负载均衡(如轮询、一致性哈希)和故障转移,避免硬编码IP。

调用流程全景

  1. 开发者调用客户端存根方法 →
  2. 存根序列化请求 →
  3. 传输层发送到服务端 →
  4. 服务端骨架反序列化并路由 →
  5. 真实服务执行业务逻辑 →
  6. 结果反向经骨架→序列化→传输层→客户端存根 →
  7. 存根将结果返回给开发者(如同本地调用)。

设计哲学:所有组件解耦,开发者只需关注业务接口定义(如PaymentService),框架自动处理“如何远程调用”。错误处理(如超时抛出RpcException)、监控(埋点调用耗时)也由框架统一实现。

三、代码框架:核心类设计与职责

一个精简的RPC框架通常包含以下核心类(以Java伪代码为例,实际框架如Dubbo结构类似)。这些类共同构成“可插拔”架构,开发者只需实现业务接口,框架自动组装调用链。

1. 业务接口定义(开发者编写)

// 定义远程服务契约(无需网络代码)

// 定义远程服务契约(无需网络代码)
public interface PaymentService {boolean deduct(String userId, double amount);
}
  • 作用:声明服务方法,是客户端存根和服务端实现的桥梁。框架通过此接口生成代理类。
2. RpcClient(客户端入口)
public class RpcClient {public <T> T createStub(Class<T> serviceInterface, String serverAddress) {// 生成动态代理存根(如JDK Proxy)return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(),new Class[]{serviceInterface},new ClientStubHandler(serverAddress) // 代理处理器);}
}
  • 作用:客户端启动器,创建服务接口的代理对象(存根)。开发者通过rpcClient.createStub(PaymentService.class, "192.168.1.100:8080")获取可调用对象。
3. ClientStubHandler(客户端存根核心)
public class ClientStubHandler implements InvocationHandler {private final String serverAddress;private final Serializer serializer = new ProtobufSerializer();private final Transport transport = new NettyTransport();@Overridepublic Object invoke(Object proxy, Method method, Object[] args) {// 1. 封装请求:方法名+参数RpcRequest request = new RpcRequest(method.getName(), args);// 2. 序列化byte[] data = serializer.serialize(request);// 3. 通过传输层发送byte[] responseBytes = transport.send(serverAddress, data);// 4. 反序列化结果return serializer.deserialize(responseBytes, method.getReturnType());}
}
  • 作用:动态代理的处理器,实现“拦截调用→序列化→发送→接收结果”的完整逻辑。关键点:将网络细节与业务代码隔离。
4. RpcServer(服务端入口)
public class RpcServer {private final Map<String, Object> serviceMap = new HashMap<>(); // 存储服务实例public void registerService(String serviceName, Object serviceImpl) {serviceMap.put(serviceName, serviceImpl);}public void start(int port) {// 启动Netty服务器,监听请求new NettyServer(port, (requestBytes) -> {RpcRequest request = serializer.deserialize(requestBytes);// 路由到真实服务return handleRequest(request);}).start();}
}
  • 作用:服务端启动器,注册真实服务实现(如paymentServiceImpl),并监听网络请求。
5. ServiceSkeleton(服务端骨架)
private Object handleRequest(RpcRequest request) {Object service = serviceMap.get(request.getServiceName());Method method = service.getClass().getMethod(request.getMethodName());// 反射调用真实方法return method.invoke(service, request.getArgs());
}
  • 作用:解析请求,通过反射调用业务逻辑。关键点:解耦网络层与业务层,新增服务只需注册实例。
6. 支撑类(框架基础设施)
  • Serializer:提供serialize()/deserialize()接口,可插拔实现(如JSONSerializer、ProtobufSerializer)。
  • Transport:封装网络通信(如NettyTransport、HttpTransport),处理连接池、重试策略。
  • Registry(扩展):集成ZooKeeper客户端,实现服务注册与发现(如ZookeeperRegistry.register("PaymentService", "192.168.1.100:8080"))。

代码设计精髓

  • 开闭原则:新增序列化协议只需实现Serializer接口,不影响核心逻辑。
  • 单一职责:每个类聚焦一件事(存根处理调用、骨架处理路由),避免“上帝类”。
  • 开发者体验:业务代码无任何RPC注解/继承,仅通过接口契约交互。

四、总结:RPC的价值与未来

        RPC框架是分布式系统的“隐形引擎”——它让开发者聚焦业务逻辑,而非网络泥潭。通过本文解析,我们看到其核心在于分层抽象:客户端存根隐藏调用细节,序列化层优化性能,传输层保障可靠性,服务端骨架解耦业务。这不仅提升了开发效率(减少70%+通信代码),更通过统一错误处理、监控埋点增强了系统韧性。

        然而,RPC并非银弹。挑战依然存在:跨语言兼容性(需IDL定义)、网络不可靠性(需重试+熔断)、版本升级(需向后兼容)。未来趋势已指向更智能的框架:

  • 云原生集成:gRPC+HTTP/2支持流式传输,适配Service Mesh;
  • 性能极致化:QUIC协议减少延迟,内存零拷贝技术提升吞吐;
  • 可观测性:OpenTelemetry自动追踪调用链,定位跨服务瓶颈。

        作为架构师或者想要成为架构师的同学,我建议:从简单场景起步(如用HTTP1.1实现两个服务通信),再逐步引入注册中心、熔断机制。记住,好的RPC框架不是炫技,而是让复杂系统回归简单——正如本地调用般自然。当你下一次设计微服务时,不妨问自己:网络细节是否该由框架扛起?答案已在代码中。

        欢迎关注、一起交流、一起进步。

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

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

相关文章

【光照】Unity中的[光照模型]概念辨析

【从UnityURP开始探索游戏渲染】专栏-直达 基础光照模型‌ ‌标准光照模型&#xff08;Standard Lighting Model&#xff09;‌ ‌定义‌&#xff1a;传统光照计算的框架&#xff0c;通常包含漫反射、镜面反射和环境光三部分。‌特点‌&#xff1a;非物理经验模型&#xff0c…

MCU上跑AI—实时目标检测算法探索

MCU上跑实时目标检测算法 前几年一直忙着别的事情没有在技术分享上下功夫, 这段时间稳定下来就想和几个志同道合的朋友做点有意义的事情, 于是乎就使用MCU做了个与AI有识别相关的 “小玩意儿”. 本人负责嵌入式端相关的编码, AI相关的工作由好友 AgeWang 负责. 这儿把一些成果给…

SpringBoot 整合 RabbitMQ 的完美实践

引言: 本文总字数:约 9200 字 预计阅读时间:38 分钟 为什么 RabbitMQ 是消息中间件的优选? 在分布式系统架构中,消息中间件扮演着 "交通枢纽" 的角色,负责协调各个服务之间的通信。目前主流的消息中间件有 RabbitMQ、Kafka 和 RocketMQ,它们各具特色: Kafka…

nestjs 发起请求 axios

1、下载npm i --save nestjs/axios axios2、全局配置import { HttpModule } from nestjs/axios;Global() Module({imports: [HttpModule.registerAsync({inject: [ConfigService],useFactory: async (configService: ConfigService) > {return {timeout: configService.get(…

将 Logits 得分转换为概率,如何计算

场景&#xff1a;动物识别&#xff0c;输入一张28*28的图像&#xff0c;模型输出属于 猫、狗、鸟 哪个类型。需求&#xff1a;假设模型 ​​Logits&#xff08;模型在每个类别的置信度得分&#xff09; 输出为​​&#xff1a;[猫: 3.2, 狗: 1.5, 鸟: -0.8]。计算 ​​Softmax …

【Qt】bug排查笔记——QMetaObject::invokeMethod: No such method

问题如题目所示&#xff1a;QMetaObject::invokeMethod: No such method xxxx&#xff0c;在网上好一顿查&#xff0c;又将查到的资料喂给了 Ai&#xff0c;才最终将问题解决&#xff0c;特此记录下。 一、问题背景 在做公司项目时&#xff0c;使用了插件的方式开发。主程序加载…

Spring Boot手写10万敏感词检查程序

使用Spring Boot手写10万敏感词检查程序 本文将介绍如何使用Spring Boot构建一个高效的敏感词检查系统,能够处理多达10万个敏感词的检测需求。我们将使用DFA(Deterministic Finite Automaton)算法来实现高效匹配,并提供RESTful API接口。 实现步骤 1. 创建Spring Boot项…

零构建的快感!dagger.js 与 React Hooks 实现对比,谁更优雅?

“Add Tags” 技术方案并行对比&#xff1a;React Hooks vs dagger.js&#xff08;含核心 JS 代码&#xff09; 源码&#xff1a; React Hooks&#xff1a;https://codepen.io/prvnbist/pen/jJzROe?editors1010dagger.js&#xff1a;https://codepen.io/dagger8224/pen/ZErjzw…

矩池云中LLaMA- Factory多机多卡训练

LLaMA Factory 是一款开源低代码大模型微调框架&#xff0c;集成了业界最广泛使用的微调技术&#xff0c;支持通过 Web UI 界面零代码微调大模型&#xff0c;目前已经成为开源社区内最受欢迎的微调框架之一。但是在矩池云上如何使用LLaMA-Factory多机多卡训练模型呢&#xff1f…

Nginx的反向代理与正向代理及其location的配置说明

一、Nginx中location匹配优先级Nginx中location匹配优先级location支持各种匹配规则&#xff0c;在多个匹配规则下&#xff0c;Nginx对location的处理是有优先级的&#xff0c;优先级高的规则会优先进行处理&#xff1b;而优先级低的规则可能会最后处理或者不进行处理。注意&am…

神经网络正则化三重奏:Weight Decay, Dropout, 和LayerNorm

正则化是机器学习中防止模型过拟合、提升泛化能力的核心技术。Weight Decay、Dropout和LayerNorm是三种最常用的方法&#xff0c;但它们的工作原理和首要目标截然不同。下面的流程图揭示了它们的核心区别与联系&#xff1a; #mermaid-svg-vymek6mFvvfxcWiM {font-family:"…

两台电脑通过网线直连共享数据,设置正确,却互相ping不通的解决方法

因为某些原因&#xff0c;需要两台电脑互传资源&#xff0c;但是某台电脑可能无法连接外网。如果手头有根网线&#xff0c;很容易想到通过一根网线连接两台电脑互传数据。 这里先说一下基本的设置&#xff1a; 两台电脑最好都关闭防火墙&#xff1b;两台电脑都打开专用网络和公…

面试新纪元:无声胜有声,让AI成为你颈上的智慧伙伴

面试&#xff0c;无论是对于面试官还是求职者&#xff0c;都像一场无声的战争。 一方要精准识人&#xff0c;一方要完美自荐&#xff1b;一方怕问不到点子上&#xff0c;一方怕答不到心坎里。 紧张、遗忘、表达失误、准备不足……这些问题几乎每个人都经历过。 有没有一种方…

qt-C++笔记之QtDesigner-Creator按钮图标与样式

qt-C笔记之QtDesigner-Creator按钮图标与样式 整理&#xff1a;如何用 .qrc 管理资源、在 Designer/Creator 中为 QPushButton 设置图标&#xff08;资源或系统主题&#xff09;&#xff0c;以及用样式表调整文字样式。涵盖 C/Qt 与 PySide/PyQt&#xff1b;Linux 桌面优先&am…

maven 常用指令

Maven 是 Java 项目构建和依赖管理的得力助手。这里为你总结了一些常用指令&#xff0c;希望能帮你提升开发效率。下面这个表格汇总了 Maven 最核心和常用的一些命令&#xff1a;命令主要功能典型使用场景mvn clean清理项目&#xff0c;删除 target 目录及其所有编译输出文件。…

# pdf.js完全指南:构建现代Web PDF查看与解析解决方案

在当今Web开发中&#xff0c;实现高质量的PDF查看功能一直是前端开发者面临的挑战之一。作为最受欢迎的JavaScript PDF库&#xff0c;pdf.js已经成为解决这一问题的行业标准。由Mozilla开发并维护的pdf.js项目&#xff0c;通过纯JavaScript实现PDF解析与渲染&#xff0c;彻底改…

高效对象属性复制工具

日常编程中&#xff0c;经常会碰到对象属性复制的场景&#xff0c;比如 VO、DTO、PO、VO 等之间的转换&#xff0c;关于什么是VO、DTO、PO、VO 等可以看上篇文章&#xff0c;VO、DTO、PO、VO 等对象具体有哪些方式可以使用呢&#xff1f; set/get 方式 性能最好的方式&#x…

大疆图传技术参数对比 你了解多少?

无人机是现代航空技术与智能控制技术结合的产物&#xff0c;已从军事领域广泛渗透至民用场景&#xff0c;成为推动各行业效率升级的关键工具。无人机的全称为 “无人驾驶航空器&#xff08;Unmanned Aerial Vehicle&#xff0c;简称 UAV&#xff09;”&#xff0c;简言之&#…

Redis 缓存热身(Cache Warm-up):原理、方案与实践

在 Redis 缓存架构中&#xff0c;“缓存热身”是指在系统正式提供服务前&#xff08;如重启、扩容后&#xff09;&#xff0c;主动将热点数据加载到 Redis 中的操作。其核心目标是避免**缓存穿透**&#xff08;请求直达数据库&#xff09;和**缓存雪崩**&#xff08;大量请求同…

基于SpringBoot的大学生就业招聘系统

1. 在线演示&#xff1a; 后台&#xff1a;http://springbootiv1oo.xiaobias.com/springbootiv1oo/admin/dist/index.html 前台&#xff1a;http://springbootiv1oo.xiaobias.com/springbootiv1oo/front/index.html 管理员&#xff1a;abo/abo 用户&#xff1a;用户1/123456、…