【分布式理论7】分布式调用之:服务间的(RPC)远程调用

文章目录

    • 一、RPC 调用过程
    • 二、RPC 动态代理:屏蔽远程通讯细节
      • 1. 动态代理示例
      • 2. 如何将动态代理应用于 RPC
    • 三、RPC序列化与协议编码
      • 1. RPC 序列化
      • 2. RPC 协议编码
        • 2.1. 协议编码的作用
        • 2.2. RPC 协议消息组成
    • 四、RPC 网络传输
      • 1. 网络传输流程
      • 2. 关键优化点

一、RPC 调用过程

RPC(Remote Procedure Call,远程过程调用)是一种让不同网络节点上的服务相互调用的技术。它的核心目标是屏蔽远程调用的复杂性,使远程服务的调用方式如同本地调用一样简单。在分布式系统中,RPC 通过封装底层网络通信细节,提高了服务调用的可用性和开发效率。

RPC 调用流程包括:

在这里插入图片描述

  1. 动态代理:客户端通过代理对象调用远程方法。
  2. 序列化:将请求数据转换为二进制格式,便于传输。
  3. 协议编码:增加数据包的协议标识和长度信息。
  4. 网络传输:通过网络传递数据包。
  5. 协议解码:服务端解析请求包。
  6. 反序列化:将二进制数据转换回原始对象。
  7. 执行方法:调用对应的远程方法并处理请求。
  8. 响应返回:按照相同的序列化、网络传输等流程将响应结果返回给调用方。

 

二、RPC 动态代理:屏蔽远程通讯细节

动态代理(Dynamic Proxy)是 Java 提供的一种机制,允许在运行时动态创建代理对象,拦截方法调用,并在调用前后执行额外的逻辑。

在 RPC 场景中,动态代理的主要作用是屏蔽底层的远程通信细节,让客户端可以像调用本地方法一样调用远程服务。

1. 动态代理示例

示例代码:

public interface ServerProvider {void sayHello(String str);
}public class ServerProviderImpl implements ServerProvider {@Overridepublic void sayHello(String str) {System.out.println("Hello " + str);}
}import java.lang.reflect.*;/**
- `DynamicProxy` 实现了 `InvocationHandler`,用于拦截方法调用并执行代理逻辑。
- `invoke` 方法中:1. `method.invoke(realObject, args);` 通过反射调用真实对象的方法。
*/
public class DynamicProxy implements InvocationHandler {private Object realObject;public DynamicProxy(Object object) {this.realObject = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return method.invoke(realObject, args);}
}public class Client {public static void main(String[] args) {ServerProvider realServer = new ServerProviderImpl();InvocationHandler handler = new DynamicProxy(realServer);ServerProvider proxyInstance = (ServerProvider) Proxy.newProxyInstance(handler.getClass().getClassLoader(),realServer.getClass().getInterfaces(),handler);proxyInstance.sayHello("world");}
}

通过动态代理,客户端不直接依赖于 ServerProviderImpl,而是通过接口和代理类进行调用,这样:

  • 解耦了客户端和服务端,不需要在客户端硬编码调用远程方法。
  • 方便在代理类中加入 RPC 逻辑,比如序列化、网络传输等。
  • 增强扩展性,可以在 invoke 方法中添加日志、权限校验、负载均衡等功能。

 

2. 如何将动态代理应用于 RPC

(1) 在代理类中加入远程调用逻辑
(2) 客户端使用代理调用远程服务

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 1. 构造 RPC 请求RpcRequest request = new RpcRequest();request.setMethodName(method.getName());request.setParameters(args);// 2. 发送请求到远程服务RpcResponse response = RpcClient.sendRequest(request);// 3. 解析响应并返回结果return response.getResult();
}ServerProvider serverProvider = (ServerProvider) Proxy.newProxyInstance(getClass().getClassLoader(),new Class[]{ServerProvider.class},new RpcDynamicProxy("http://remote-server")
);
serverProvider.sayHello("world");

如果想进一步实现 RPC 的完整流程,可以加入序列化、网络传输、反序列化等模块,搭建一个真正的 RPC 组件!

 

三、RPC序列化与协议编码

1. RPC 序列化

序列化是将对象转换成字节流的过程,而反序列化则是恢复对象的过程。常见的序列化方式包括:

  • JSON:易读易用,但额外空间开销较大。
  • Hessian:二进制格式,序列化后字节数小,性能优于 JSON。
  • Protobuf:高效、跨语言支持,适用于大规模分布式应用。
  • Thrift:Facebook 开源的高效序列化框架,结合了 RPC 服务框架。

 

2. RPC 协议编码

2.1. 协议编码的作用

有了序列化功能,就可以将客户端的请求对象转化成字节流在网络上传输了,这个字节流转换为二进制信息以后会写入本地的 Socket 中,然后通过网卡发送到服务端。从编程角度来看,每次请求只会发送一个请求包,但是从网络传输的角度来看,网络传输过程中会将二进制包拆分成很多个数据包,这一点也可以从 TCP 传输数据的原理看出。拆分后的多个二进制包会同时发往服务端,服务端接收到这些数据包以后,将它们合并到一起,再进行反序列化以及后面的操作。

实际上,协议编码要做的事情就是对同一次网络请求的数据包进行拆分,并且为拆分得到的每个数据包定义边界、长度等信息。

 

2.2. RPC 协议消息组成

RPC 协议消息由 消息头消息体 组成:

  • 消息头 包含协议标识、数据长度、请求类型等信息。
  • 消息体 是序列化后的数据。

协议编码的核心目标是确保数据包正确地分片、合并,并提供必要的描述信息,保障网络传输的可靠性。

消息头部分主要存放消息本身的描述信息,如图所示。
在这里插入图片描述

名称描述
魔术位(magic)协议魔术,为解码设计
消息头长度(header size)用来描述消息头长度,为扩展设计
协议版本(version)协议版本,用于版本兼容
消息体序列化类型(st)描述消息体的序列化类型,例如 JSON、gRPC
心跳标记(hb)每次传输都会建立一个长连接,隔一段时间向接收方发送一次心跳请求,保证对方始终在线
单向消息标记(ow)标记是否为单向消息
响应消息标记(rp)用来标记是请求消息还是响应消息
响应消息状态码(status code)标记响应消息状态码
保留字段(reserved)用于填充消息,保证消息的字节是对齐的
消息 Id(message id)用来唯一确定一个消息的标识
消息体长度(body size)描述消息体的长度

 

四、RPC 网络传输

1. 网络传输流程

在 RPC 调用中,服务调用方(Client)需要发送请求给服务提供方(Server),然后等待服务器处理并返回响应数据。在这个过程中,数据在应用程序、操作系统内核、网络传输三个层次之间流动,并涉及多个数据复制操作。

从示意图中可以看出,数据的流转主要分为两部分:请求发送过程响应接收过程

在这里插入图片描述

请求发送流程(Client -> Server),服务调用方(Client)发起 RPC 请求,其数据流动过程如下:

步骤操作数据位置
1应用程序写入数据业务代码执行RPC调用,将数据写入应用缓冲区(User Space)
2数据复制到内核缓冲区操作系统将应用缓冲区的数据复制到内核缓冲区(Kernel Space)
3通过网络发送数据从内核缓冲区被传输到网卡(Network Card),并通过网络协议(如TCP)拆分成数据包发送到远程服务器
4服务器接收数据服务器端网卡接收数据包,并将其存入内核缓冲区
5数据复制到应用缓冲区服务器的内核将数据复制到应用缓冲区
6应用程序读取数据服务器端应用程序从应用缓冲区中获取数据,执行请求逻辑(如数据库查询、业务处理)

响应接收流程(Server -> Client):服务提供方(Server)处理完请求后,将结果返回给客户端,数据流动过程如下:

步骤操作具体内容
7应用程序写入数据服务器应用程序生成响应数据,并写入应用缓冲区
8数据复制到内核缓冲区服务器操作系统将数据从应用缓冲区复制到内核缓冲区,准备发送
9通过网络发送服务器的网卡将数据包发送到客户端
10客户端接收数据客户端网卡接收数据包,操作系统将其存入内核缓冲区
11数据复制到应用缓冲区数据从内核缓冲区复制到应用缓冲区,以便应用程序使用
12应用程序读取数据客户端应用程序从应用缓冲区中获取响应数据,完成 RPC 调用

通过上面对 RPC 调用流程的描述,可以看出服务调用方需要经过一系列的数据复制,才能通过网络传输将信息发送到服务提供方。此外可以看出网络 IO 传输和数据计算过程存在先后顺序,因此当前者出现延迟时会导致后者处于阻塞。另外,应用程序中存在同步调用和异步调用,因此衍生出了同步阻塞 IO(blocking IO)​、同步非阻塞 IO(non-blocking IO)​、多路复用 IO(multiplexing IO)这几种 IO 模式。(下篇分析ing)

 

2. 关键优化点

RPC 网络传输过程涉及多个阶段,包括数据在应用缓冲区、内核缓冲区、网络传输中的流转。优化 RPC 传输的关键在于减少数据复制、优化网络通信、使用异步 I/O 机制,提高整体性能。

操作具体内容
减少数据复制采用 零拷贝(Zero-Copy) 技术,如 mmapsendfile,避免数据在用户态和内核态之间频繁复制
优化网络传输使用 长连接(Keep-Alive) 避免频繁建立 TCP 连接;采用 批量发送数据压缩 来减少数据传输的开销
异步 I/O 处理使用 异步 I/O(如 Netty、epoll),避免同步阻塞,提高并发处理能力
优化缓冲区管理采用 池化缓冲区(Buffer Pool) 避免频繁申请和释放内存

 

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

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

相关文章

综合评价 | 基于随机变异系数-TOPSIS组合法的综合评价模型(Matlab)

基于随机变异系数-TOPSIS组合法的综合评价模型 代码获取私信回复:综合评价 | 基于随机变异系数-TOPSIS组合法的综合评价模型(Matlab) 一、引言 1.1、研究背景与意义 在现代社会,随着信息量的不断增加和数据复杂性的提升&#…

采用分步式无线控制架构实现水池液位自动化管理

以下是基于巨控GRM241Q-4D4I4QHE模块的完整技术方案,采用分步式无线控制架构实现水池液位自动化管理: 一、系统架构设计 硬件部署 山顶单元 GRM241Q模块(带4G功能) 液位计(4-20mA) 功能:实时采…

Vue设计模式到底多少种?

Vue设计模式到底多少种? 很多同学问,Vue到底有多少种设计模式??各个模式到底是什么意思??又各自适合什么场景?? 这里我给大家直接说下,Vue的设计模式没有一个固定的数值…

[LeetCode] day19 454. 四数相加 II

题目链接 题目描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1&#xff1a; 输入&…

查看二进制程序内的 .interp 段

synopsis 可以使用 readelf &#xff0c;objdump&#xff0c;hexdump等工具查看 二进制程序内的.interp段信息。 1. 使用readelf查看.interp段 readelf 是一个查看ELF&#xff08;Executable and Linkable Format&#xff09;文件信息的工具&#xff0c;特别适合查看ELF头和…

【时时三省】(C语言基础)基础习题1

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 1.什么是程序&#xff1f;什么是程序设计 程序是为实现特定目标或解决特定问题&#xff0c;用计算机能理解和执行的语言编写的一系列指令的集合。 程序设计是问题分析&#xff0c;设计算法…

食品饮料生产瓶颈?富唯智能协作机器人来 “破壁”

在食品和饮料行业的发展进程中&#xff0c;诸多生产瓶颈如重复性劳动负担、复杂环境作业难题、季节性产能波动等&#xff0c;长期制约着企业的高效运营与进一步发展。如今&#xff0c;富唯智能协作机器人的出现&#xff0c;为这些难题提供了完美的解决方案&#xff0c;正逐步改…

[创业之路-289]:《产品开发管理-方法.流程.工具 》-15- 需求管理 - 第1步:原始需求收集

概述&#xff1a; 需求收集是需求管理的第一步&#xff0c;也是产品开发、项目管理或软件设计中的关键步骤。原始需求收集主要是指从各种来源获取关于产品或服务的初步需求和期望。 以下是对需求管理中的原始需求收集的详细分析&#xff1a; 1、原始需求收集的目的 原始需求…

81页精品PPT | 华为流程与信息化实践与架构规划分享

华为流程与信息化实践与架构规划分享主要围绕华为在业务流程与信息化建设方面的经验、企业架构规划方法以及企业数字化转型路径展开。华为通过持续的业务变革和信息化建设&#xff0c;从本土企业逐步发展为国际化、全球化企业&#xff0c;其管理体系以持续创新和世界级管理体系…

DeepSeek 实践总结

目录 1、与AI对话-万能公式 chatbox 谷歌插件方式 命令行方式 2、ChatPPT+DeepSeek形成PPT 1、与AI对话-万能公式 *明确身份+任务+细节描述+输出格式* 这样的方式能更加准确的帮助你快速获得接近你想法的内容。 身份:你是谁?(网络负责人/记者/老师。。。)任务:要解决什…

51c自动驾驶~合集49

我自己的原文哦~ https://blog.51cto.com/whaosoft/13164876 #Ultra-AV 轨迹预测新基准&#xff01;清华开源&#xff1a;统一自动驾驶纵向轨迹数据集 自动驾驶车辆在交通运输领域展现出巨大潜力&#xff0c;而理解其纵向驾驶行为是实现安全高效自动驾驶的关键。现有的开…

【AI学习】LLM的发展方向

个人的思考&#xff0c;请大家批评。 这一轮AI浪潮&#xff0c;叙事的主要逻辑就是scaling law&#xff0c;模型越大&#xff0c;性能越好&#xff0c;投入越大&#xff0c;性能越好&#xff0c;回报越高&#xff0c;等等。当然&#xff0c;首先要有一个能够scaling的模型架构…

C语言学习笔记:子函数的调用实现各个位的累加和

在C语言程序学习之初&#xff0c;我们都会学习如何打印 hello world&#xff0c;在学习时我们知道了int main&#xff08;&#xff09;是主函数&#xff0c;程序从main函数开始执行&#xff0c;这是流程控制的一部分内容。在主函数中我们想要实现一些功能&#xff0c;比如求各个…

白话文实战Nacos(保姆级教程)

前言 上一篇博客 我们创建好了微服务项目,本篇博客来体验一下Nacos作为注册中心和配置中心的功能。 注册中心 如果我们启动了一个Nacos注册中心,那么微服务比如订单服务,启动后就可以连上注册中心把自己注册上去,这过程就是服务注册。每个微服务,比如商品服务都应该注册…

2025.2.9 每日学习记录2:技术报告写了一半+一点点读后感

0.近期主任务线 1.完成小论文准备 目标是3月份完成实验点1的全部实验和论文。 2.准备教资笔试 打算留个十多天左右&#xff0c;一次性备考笔试的三个科目 1.实习申请技术准备&#xff1a;微调、Agent、RAG 1.今日完成任务 1.电子斗蛐蛐&#xff08;文本书写领域&am…

【Git】ssh如何配置gitlab+github

当我们工作项目在gitlab上&#xff0c;又希望同时能更新自己个人的github项目时&#xff0c;可能因为隐私问题&#xff0c;不能使用同一′密钥。就需要在本地电脑上分别配置两次ssh。 1、分别创建ssh key 在用户主目录下&#xff0c;查询是否存在“.ssh”文件&#xff1a; 如…

【设计模式】【行为型模式】职责链模式(Chain of Responsibility)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f4eb; 欢迎V&#xff1a; flzjcsg2&#xff0c;我们共同讨论Java深渊的奥秘 &#x1f…

Spring Boot牵手Redisson:分布式锁实战秘籍

一、引言 在当今的分布式系统架构中,随着业务规模的不断扩大和系统复杂度的日益增加,如何确保多个服务节点之间的数据一致性和操作的原子性成为了一个至关重要的问题。在单机环境下,我们可以轻松地使用线程锁或进程锁来控制对共享资源的访问,但在分布式系统中,由于各个服务…

apache-poi导出excel数据

excel导出 自动设置宽度&#xff0c;设置标题框&#xff0c;设置数据边框。 excel导出 添加依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>…

畅游Diffusion数字人(16):由音乐驱动跳舞视频生成

畅游Diffusion数字人(0):专栏文章导航 前言:从Pose到跳舞视频生成的工作非常多,但是还没有直接从音乐驱动生成的工作。最近字节跳动提出了MuseDance,无需复杂的动作引导输入(如姿势或深度序列),从而使不同专业水平的用户都能轻松进行灵活且富有创意的视频生成。 目录 贡…