RPC实现原理

article/2025/9/26 19:44:22

一、什么是RPC框架?

RPC,全称为Remote Procedure Call,即远程过程调用,是一种计算机通信协议。
比如现在有两台机器:A机器和B机器,并且分别部署了应用A和应用B。假设此时位于A机器上的A应用想要调用位于B机器上的B应用提供的函数或是方法,由于A应用和B应用不在一个内存空间里面,所以不能直接调用,此时就需要通过网络来表达调用的方式和传输调用的数据。也即所谓的远程调用。

二、RPC框架的实现原理?

主要有以下几个步骤:

1、建立通信

首先要解决通讯的问题:即A机器想要调用B机器,首先得建立起通信连接。主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有相关的数据都在这个连接里面进行传输交换。

通常这个连接可以是按需连接(需要调用的时候就先建立连接,调用结束后就立马断掉),也可以是长连接(客户端和服务器建立起连接之后保持长期持有,不管此时有无数据包的发送,可以配合心跳检测机制定期检测建立的连接是否存活有效),多个远程过程调用共享同一个连接。

2、服务寻址

解决寻址的问题:即A机器上的应用A要调用B机器上的应用B,那么此时对于A来说如何告知底层的RPC框架所要调用的服务具体在哪里呢?

通常情况下我们需要提供B机器(主机名或IP地址)以及特定的端口,然后指定调用的方法或者函数的名称以及入参出参等信息,这样才能完成服务的一个调用。比如基于Web服务协议栈的RPC,就需要提供一个endpoint URI,或者是从UDDI服务上进行查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。

3、网络传输

3.1、序列化

当A机器上的应用发起一个RPC调用时,调用方法和其入参等信息需要通过底层的网络协议如TCP传输到B机器,由于网络协议是基于二进制的,所有我们传输的参数数据都需要先进行序列化(Serialize)或者编组(marshal)成二进制的形式才能在网络中进行传输。然后通过寻址操作和网络传输将序列化或者编组之后的二进制数据发送给B机器。

3.2、反序列化

当B机器接收到A机器的应用发来的请求之后,又需要对接收到的参数等信息进行反序列化操作(序列化的逆操作),即将二进制信息恢复为内存中的表达方式,然后再找到对应的方法(寻址的一部分)进行本地调用(一般是通过生成代理Proxy去调用, 通常会有JDK动态代理、CGLIB动态代理、Javassist生成字节码技术等),之后得到调用的返回值。

4、服务调用

B机器进行本地调用(通过代理Proxy)之后得到了返回值,此时还需要再把返回值发送回A机器,同样也需要经过序列化操作,然后再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作,恢复为内存中的表达方式,最后再交给A机器上的应用进行相关处理(一般是业务逻辑处理操作)。

通常,经过以上四个步骤之后,一次完整的RPC调用算是完成了,另外可能因为网络抖动等原因需要重试等。

三、为什么需要RPC?

主要就是因为在几个进程内(应用分布在不同的机器上),无法共用内存空间,或者在一台机器内通过本地调用无法完成相关的需求,比如不同的系统之间的通讯,甚至不同组织之间的通讯。此外由于机器的横向扩展,需要在多台机器组成的集群上部署应用等等。

四、RPC支持哪些协议?

最早的CORBA、Java RMI, WebService方式的RPC风格, Hessian, Thrift甚至Rest API。

五、RPC的实现基础?

  1. 1、需要有非常高效的网络通信,比如一般选择Netty作为网络通信框架
  2. 2、需要有比较高效的序列化框架,比如谷歌的Protobuf序列化框架
  3. 3、可靠的寻址方式(主要是提供服务的发现),比如可以使用Zookeeper来注册服务等等
  4. 4、如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能

六、RPC调用过程?

6.1 一个基本的RPC架构里面应该至少包含以下4个组件:

  1. 1、客户端(Client):服务调用方(服务消费者)
  2. 2、客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
  3. 3、服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
  4. 4、服务端(Server):服务的真正提供者

6.2 具体的调用过程如下:

  1. 1、服务消费者(client客户端)通过本地调用的方式调用服务
  2. 2、客户端存根(client stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体
  3. 3、客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端
  4. 4、服务端存根(server stub)收到消息后进行解码(反序列化操作)
  5. 5、服务端存根(server stub)根据解码结果调用本地的服务进行相关处理
  6. 6、本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub)
  7. 7、服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方
  8. 8、客户端存根(client stub)接收到消息,并进行解码(反序列化)
  9. 9、服务消费方得到最终结果

image.png

而RPC框架的实现目标则是将上面的第2-10步完好地封装起来,也就是把调用、编码/解码的过程给封装起来,让用户感觉上像调用本地服务一样的调用远程服务。

七、RPC框架需要解决的问题?

  1. 1、如何确定客户端和服务端之间的通信协议?
  2. 2、如何更高效地进行网络通信?
  3. 3、服务端提供的服务如何暴露给客户端?
  4. 4、客户端如何发现这些暴露的服务?
  5. 5、如何更高效地对请求对象和响应结果进行序列化和反序列化操作?

八、使用了哪些技术?

8.1、动态代理

生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到java动态代理技术,可以使用jdk提供的原生的动态代理机制,也可以使用开源的:Cglib代理,Javassist字节码生成技术。

8.2、序列化

在网络中,所有的数据都将会被转化为字节进行传送,所以为了能够使参数对象在网络中进行传输,需要对这些参数进行序列化和反序列化操作。

序列化:把对象转换为字节序列的过程称为对象的序列化,也就是编码的过程。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。

目前比较高效的开源序列化框架:如Kryo、fastjson和Protobuf等。

8.3、NIO通信

出于并发性能的考虑,传统的阻塞式 IO 显然不太合适,因此我们需要异步的 IO,即 NIO。
Java 提供了 NIO 的解决方案,Java 7 也提供了更优秀的 NIO.2 支持。可以选择Netty或者mina来解决NIO数据传输的问题。

8.4、服务注册中心

可选:Redis、Zookeeper、Consul 、Etcd。
一般使用ZooKeeper提供服务注册与发现功能,解决单点故障以及分布式部署的问题(注册中心)。



作者:hu1991die
链接:https://www.jianshu.com/p/78f72ccf0377
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

</article>

http://chatgpt.dhexx.cn/article/pxk2J611.shtml

相关文章

什么是 RPC?RPC原理是什么?

什么是 RPC?RPC原理是什么? 什么是 RPC&#xff1f; RPC&#xff08;Remote Procedure Call&#xff09;—远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器…

【RK3399Pro学习笔记】三、Debian 9 安装 ROS (Thinker Edge R)

目录 配置源设置 Key安装初始化rosdep环境配置测试安装rosinstall卸载 平台&#xff1a;华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本&#xff1a;Tinker_Edge_R-Debian-Stretch-V1.0.4-20200615 参考资料&#xff1a; RK3399(Debian9 - stretch) 安装 ROS Lunar —— WB8…

VMware安装Debian9及开发环境配置

序 需要用到一个搭载armv7架构A7内核的Linux设备&#xff0c;装的是Debian系统&#xff0c;为便于兼容该设备故用VMware安装一个Debian9虚拟机&#xff0c;整理总结了网上一些信息以供参考。 目录 一、安装Debian91、WMware中的配置2、安装镜像 二、开发环境配置1、设置快捷键打…

debian 升级linux内核,Debian 9更新到最新的Linux内核

喜欢折腾的同学,会豪气如何升级 Debian Stretch 的内核到新版。遗憾的是现在能搜到的升级 Debian Linux 内核的文章多数是使用Ubuntu的deb安装包,其实这样装上去是有问题,常见的问题是,总会提示需要 apt --fix-broken install 。 这里简单记录一下,如何使用Debian官方源更…

debian 9 ssh root权限登录

debian 9默认的一样不能用root用户登录&#xff0c;还是需要设置&#xff0c;方法如下&#xff1a; 一&#xff0c;打开终端&#xff0c;用普通用户登录 输入&#xff1a;su - 输入密码&#xff0c;切换到root用户 二&#xff0c;设置root用户登录 nano /etc/ssh/sshd_conf…

Debian9到Debian11的超详细升级教程

在云服务器商镜像页面中&#xff0c;可能无法选择一些系统最新的镜像版本。 就会造成一些软件不能顺利下载。 这时就需要自己手动下载并安装最新版的Debian系统了。 1、把当前版本的包更新到最新的版本 apt-get update apt-get upgrade apt-get dist-upgrade按q 直接回车 …

【linux实战】debian9安装python3.7

之前有写了一篇ubuntu18.04使用apt安装python各个版本的&#xff0c;但是最近上debian9上&#xff0c;发现那种apt安装方式不可行&#xff0c;因为ppa不支持debian系列。 Debian 9 默认安装有 Python 2.7 和 3.5。但是我们现在没法使用apt直接安装是没法安装自己想要的版本。 …

debian 系统启动服务器,Debian9添加开机自启动服务

升级到Debian9后&#xff0c;我们发现系统默认不带/etc/rc.local文件&#xff0c;但rc.local服务仍然保留 补齐缺失文件&#xff0c;让Debian9通过编辑/etc/rc.loacl文件为我们的服务添加开机自启动 1、添加rc-local.service #以下为一整条命令&#xff0c;一起复制运行cat >…

debian服务器系统安装,安装Debian 9(Stretch)最小服务器

在本指南中,我们将引导您使用netinstall CD ISO映像安装Debian 9(Stretch)Minimal Server 。 您将执行的此安装适用于构建未来可定制的服务器平台,而无需GUI(图形用户界面)。 您可以使用它来安装仅需要使用的必需软件包,我们将在将来的指南中向您展示。 但是,在进一步了解系…

debian9服务器系统,如何安装Debian 9(Stretch)最小服务器

本教程将介绍如何安装Debian 9(Stretch)最小服务器。 本指南的目的是提供一个最小的Debian设置&#xff0c;可以作为我们其他Debian 9教程的基础&#xff0c;以及在howtoing.com上完美的服务器指南 。 1要求 要安装Debian 9服务器系统&#xff0c;您将需要以下内容&#xff1a;…

debian9软件源的设置

文章目录 debian9软件源的设置概述笔记END debian9软件源的设置 概述 今天和同学讨论一个在debian9下自产软件的细节, 需要先编译这个软件工程. 他说在debian9或debian10下都可以编译. 我本地debian9虚拟机编译失败. 因为我这虚拟机环境是从.iso装的, 装到可以访问外网就做了…

IDEA连接数据库失败

问题描述 IDEA连接数据库输入用户名密码后点击测试连接&#xff0c;返回failed连接失败。 点击view查看失败原因 提示错误号为08001 分析原因 MySql 5.X版本和MySql8.X版本之间有个比较大的区别&#xff0c;MySql8.X在连接的时候需要设置时区&#xff0c;否则连接失败。 …

PHP连接数据库失败-解决方案

问题描述 今天在使用php代码连接数据库的时候发现死活都连接不上&#xff0c;在确认账号密码都没有错误的情况下&#xff0c;几乎找遍了答案都无法解决。 解决方法 通过不断的查阅资料及测试&#xff0c;发现问题在于本机地址localhost和127.0.0.1身上&#xff0c;当我把l…

用php连接数据库步骤,php连接数据库步骤详细介绍

本篇文章为大家简述一下PHP与数据库连接步骤&#xff0c;仅供参考。 1&#xff1a;链接数据库 ①主机地址 ②mysql用户名 ③mysql密码 ④选择连接的数据库 ⑤端口号mysqli_connect($localhost, $user, $password, $port); 返回&#xff1a;如果连接成功&#xff0c;返回资源类型…

CDH 5.13 hue数据库连接测试失败

在自己的虚拟机部署了好几次hue连接测试不通过&#xff0c;暂时用不到hue&#xff0c;就一直没有管。 路径; /opt/cm-5.13.1/log/cloudera-scm-server 执行 tail -n 500 cloudera-scm-server.log 报错信息&#xff1a; 解决办法&#xff1a;安装mysql的时候&#xff0c;将…

用友系统中连接数据库服务器失败,用友u8服务器连接不到本地数据库

用友u8服务器连接不到本地数据库 内容精选 换一换 创建外表语法(CREATE FOREIGN TABLE (SQL on Hadoop or OBS))中,需指定一个与MRS数据源连接相关联的外部服务器。当您通过GaussDB(DWS)管理控制台创建MRS数据源连接时,数据库管理员dbadmin会在默认数据库gaussdb中自动创建一…

达梦数据库连接失败解决方式

打开达梦数据库之后&#xff0c;连接失败&#xff0c;检查主机名、用户名、口令后依旧出现下图错误 点开详情后&#xff0c;提示错误消息&#xff1a;网络通信异常 排查发现&#xff0c;本地的达梦服务没有启动 解决办法&#xff1a; 首先&#xff0c;打开任务管理器里面的服…

关于Java连接mysql数据库失败的一种检查思路

今天学习《Java从入门到精通》李晓波版本时&#xff0c;用Java连接数据库失败&#xff0c;报了下面错误 这里贴个连接数据库的代码 package del; import java.sql.*; public class Java16_1 {public static void main(String[] args) {// TODO Auto-generated method stubConn…

eclipse连接数据库

数据库连接是很让人烦的一件事&#xff0c;因为状况百出&#xff0c;下面我就来说一下我连接的过程。 右击一个项目 下面就可以开始检查是否连接成功了! import java.sql.Connection; import java.sql.DriverManager;/*** 数据库工具类* author Administrator**/ public class …

关于Navicat连接本地数据库失败,报错2003

在连接虚拟机中数据库时成功的&#xff0c;在连接本地数据库显示失败 下图所示&#xff0c;连接数据库失败 在查找多方资料后 1.使用管理员权限 安装mysql服务器 输入命令&#xff1a;mysqld --install 2. 启动mysql服务 net start mysql 3. 启动数据库 在dos窗口输入&#…