RPC通信基本原理 -- 浅析RPC远程过程调用基本原理

article/2025/10/4 3:36:08

一、RPC基本概念

1.1、RPC简介

  • RPC 的全称是 Remote Procedure Call是一种进程间通信方式。
  • RPC只是一个概念 而不是具体的协议或框架。
  • 它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
  • 即程序员无论是调用本地的还是远程的,本质上编写的调用代码基本相同。
  • 它可以有不同的实现方式。如RMI(远程方法调用)、Hessian、Http invoker等。另外,RPC是与语言无关的。

在这里插入图片描述
如上图所示,假设Computer1在调用sayHi()方法,对于Computer1而言调用sayHi()方法就像调用本地方法一样,调用 –>返回。但从后续调用可以看出Computer1调用的是Computer2中的sayHi()方法,RPC屏蔽了底层的实现细节,让调用者无需关注网络通信,数据传输等细节。

1.2、RPC架构

一个完整的RPC架构里面包含了四个核心的组件,分别是Client,Client Stub,Server以及Server Stub,这个Stub可以理解为存根。

  • 客户端(Client),服务的调用方。
  • 客户端存根(Client Stub),存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
  • 服务端(Server),真正的服务提供者。
  • 服务端存根(Server Stub),接收客户端发送过来的消息,将消息解包,并调用本地的方法。

1.3 RPC调用过程

在这里插入图片描述

  • (1) 客户端(client)以本地调用方式(即以接口的方式)调用服务;

  • (2) 客户端存根(client stub)接收到调用后,负责将方法、参数等组装成能够进行网络传输的消息体(将消息体对象序列化为二进制);

  • (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这些步骤都封装起来。

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

1.4、作用及优势

在这里插入图片描述

1、作用:

  • 1、使服务解耦
  • 2、分布式设计
  • 3、部署灵活
  • 4、容易扩展

2、优点:

  • 1、一般使用长链接,不必每次通信都要3次握手,减少网络开销
  • 2、一般都有注册中心,有丰富的监控管理
  • 3、发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作
  • 4、协议私密,安全性较高
  • 5、rpc 能做到协议更简单内容更小,效率更高
  • 6、rpc是面向服务的更高级的抽象,支持服务注册发现,负载均衡,超时重试,熔断降级等高级特性

二、RPC架构解析

2.1、RPC架构分析

RPC的定义:远程过程调用,调用远程就像调用本地某个过程或函数。通过这一句我们是不是感受不到IP等地址信息的存在了,请求头是不是也应该存在了,编码什么的也不复存在了吧,网络传输不应该让我们开发者感受到了吧…中间的所有跟调用过程相关的是不是都是RPC内部应该帮我们做的,那么接下来我们看一下RPC中具体应该有哪些模块,每个模块又有什么存在的意义

在这里插入图片描述

- 
- 1、调用模块:通过该模块对数据进行封装、对请求进行负载、超时判断、熔断和限流等等
- 2、序列化	: 通过该模块对数据进行序列化,转成可通过网络传输的格式,并在没收到数据后反序列化成可读的格式
- 3、协议编码:这里的编码是对数据的编码和解码
- 4、网络传输:两个服务之间信息的传输
- 5、服务发现:从注册中心订阅服务
- 6、服务注册:将服务提供者提供的服务注册到注册中心供消费者使用
- 7、注册中心:在高可用的生产环境中,服务一般都以集群方式提供服务,集群里面的IP等重要参数信息可能随时会发生变化,节点也可能会动态扩缩容,客户端需要能够及时感知服务端的变化,获取集群最新服务节点的连接信息,而这些变化要求是要对调用方应用无感知的
- 

2.2、RPC框架的实现

上面介绍了RPC的核心原理:RPC能够让本地应用简单、高效地调用服务器中的过程(服务)。它主要应用在分布式系统。如Hadoop中的IPC组件。但怎样实现一个RPC框架呢?

2.1.1、从下面几个方面思考,仅供参考:

  • 1.通信模型:假设通信的为A机器与B机器,A与B之间有通信模型,在Java中一般基于BIONIO;。

  • 2.过程(服务)定位:使用给定的通信方式,与确定IP与端口及方法名称确定具体的过程或方法;

  • 3.远程代理对象:本地调用的方法(服务)其实是远程方法的本地代理,因此可能需要一个远程代理对象,对于Java而言,远程代理对象可以使用Java的动态对象实现,封装了调用远程方法调用;

  • 4.序列化,将对象名称、方法名称、参数等对象信息进行网络传输需要转换成二进制传输,这里可能需要不同的序列化技术方案。如:protobuf,Arvo

2.1.2、hdfs的RPC基本流程:

在这里插入图片描述
hdfs的rpc流程基本如上,其中的关键就是获得NameNode代理对象。

2.3、JAVA中代理方式

2.2.1、什么是代理模式

  • 1.定义:为其他对象提供一种代理以控制对这个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

  • 2.例子:最开始接触JDBC操作数据库的时候,业务层每一个方法都需要做以下几件事

    (1)打开数据库连接

    (2)执行我们想要的操作

    (3)关闭数据库连接

此时,我的核心业务是第(2)步,其余两步为辅助业务。当核心业务与辅助业务写在了一个方法中时。会出现以下问题:

 ① 代码业务冗余② 开关数据库连接大量的重复
  • 3.通过代理模式,我们可以抽取出核心业务与辅助业务

2.2.2、静态代理与动态代理

对 JAVA 来说就是使用代理!java代理有两种方式

  • (1)静态代理

先定义一个公共接口,里面包括了可以通过RPC调用的方法列表。而且被代理对象以及对象本身都需要实现该接口
尽管字节码生成方式实现的代理更为强大和高效,但代码不易维护,大部分公司实现RPC框架时还是选择动态代理方式

  • (2)动态代理

先定义一个公共接口,里面包括了可以通过RPC调用的方法列表。被代理对象以及对象本身都不需要实现该接口。而是通过匿名内部类+反射的机制实现。hadoop就是使用这种方式。

  • 1.实现InvocationHandle接口,该接口所在位置为:java.lang.reflect.InvocationHandler

  • 2.该接口中有一个方法Object invoke(Object proxy, Method method, Object[] args)

    (1)Ojbect proxy:表示需要代理的对象

    (2)Method method:表示要操作的方法

    (3)Object[] args:method方法所需要传入的参数(可能没有为,null.也可能有多个)

  • 3.代理类 java.lang.reflect.ProxyProxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类)

  • 4.调用代理类中的方法


public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException参数:(1)loader - 定义代理类的类加载器(2)interfaces - 代理类要实现的接口列表(3)h - 指派方法调用的调用处理程序返回:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口

2.4、hadoop RPC框架的例子

Server:


/*
MyInterface.java	
*/
package Server;import org.apache.hadoop.ipc.VersionedProtocol;public interface MyInterface extends VersionedProtocol {public static long versionID = 1001; //这个是标记RPC的client和server对应的标记public String helloWorld(String name);
}/*
MyImpl.java
*/
package Server;import org.apache.hadoop.ipc.ProtocolSignature;import java.io.IOException;public class MyImpl implements MyInterface{/*这是实际目标*///重写我们在上面接口自定义的方法@Overridepublic String helloWorld(String name) {return "hello," + name;}//返回版本号@Overridepublic long getProtocolVersion(String s, long l) throws IOException {return MyInterface.versionID;}//返回签名信息@Overridepublic ProtocolSignature getProtocolSignature(String s, long l, int i) throws IOException {return new ProtocolSignature(MyInterface.versionID, null);}
}/*
MyRpcServer.java
*/
package Server;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;import java.io.IOException;public class MyRpcServer {public static void main(String[] args) {//建立rpc通道对象RPC.Builder builder = new RPC.Builder(new Configuration());//设置RPC server参数builder.setBindAddress("localhost");builder.setPort(7788);//部署程序,传入实现server业务代码的接口定义,这里面包括了该rpcserver 可以提供的方法,也就是给client调用的方法列表,通过反射的方式引入类对象builder.setProtocol(MyInterface.class);//部署接口的实现类对象builder.setInstance(new MyImpl());//开启servertry {RPC.Server server = builder.build();server.start();} catch (IOException e) {e.printStackTrace();}}
}

client:


/*
MyRpcClient.java
*/
package Client;import Server.MyInterface;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;import java.io.IOException;
import java.net.InetSocketAddress;public class MyRpcClient {public static void main(String[] args) {try {//获取代理对象,设置接口类对象、RPC通信的versionID,rpcserver地址、configuration对象MyInterface proxy = RPC.getProxy(MyInterface.class,MyInterface.versionID,new InetSocketAddress("localhost", 7788),new Configuration());//获得代理对象之后,就可以通过proxy调用接口类中的方法,这里就调用上面定义的 helloWorld对象System.out.println(proxy.helloWorld("king"));} catch (IOException e) {e.printStackTrace();}}
}

下面启动server端和client端,执行结果为:

//server:可以看到显示监听端口 7788
[main] INFO org.apache.hadoop.ipc.CallQueueManager - Using callQueue: class java.util.concurrent.LinkedBlockingQueue queueCapacity: 100 scheduler: class org.apache.hadoop.ipc.DefaultRpcScheduler
[Socket Reader #1 for port 7788] INFO org.apache.hadoop.ipc.Server - Starting Socket Reader #1 for port 7788
[IPC Server Responder] INFO org.apache.hadoop.ipc.Server - IPC Server Responder: starting
[IPC Server listener on 7788] INFO org.apache.hadoop.ipc.Server - IPC Server listener on 7788: starting//client:  我们传入“King”作为参数,能够争取执行
hello,king

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

相关文章

RPC服务调用

RPC服务调用 一、RPC实现原理深入分析1、RPC的定义&#xff08;1&#xff09;RPC作用&#xff08;2&#xff09;RPC核心组成&#xff08;3&#xff09;RPC调用方式 二、精简版RPC调用代码实现1、场景2、接口设计3、序列化协议 最近在做调用系统相关的服务&#xff0c;采用主从的…

远程过程调用(RPC)详解

本文介绍了什么是远程过程调用(RPC)&#xff0c;RPC 有哪些常用的方法&#xff0c;RPC 经历了哪些发展阶段&#xff0c;以及比较了各种 RPC 技术的优劣。 什么是 RPC RPC 是远程过程调用&#xff08;Remote Procedure Call&#xff09;的缩写形式&#xff0c;Birrell 和 Nels…

Simple Schnorr Multi-Signatures with Applications to Bitcoin 学习笔记

1. 引言 Blockstream团队2018年论文《Simple Schnorr Multi-Signatures with Applications to Bitcoin》。 对应的代码实现&#xff1a; https://github.com/KZen-networks/multi-party-schnorr https://github.com/lovesh/signature-schemes 论文要点&#xff1a; MuSig——…

【密码学原理】数字签名(ElGamal签名,Schnorr签名,椭圆曲线签名,RSA-PSS签名)

数字签名是公钥密码学发展过程中最重要的概念之一&#xff0c;产生和使用数字签名过程的一般模型如图所示 消息认证可以保护消息交换双方不受第三方的攻击&#xff0c;但是不能处理通信双方自身发生的攻击。例如对下图中的某种方式进行攻击&#xff0c;考虑两种情况&#xff1a…

Schnorr签名java实现

Schnorr签名&#xff08;模指数&#xff09;的实现java 1、算法描述2、算法的实现&#xff08;java&#xff09; 和ElGama数字签名一样&#xff0c;Schnorr数字签名方案也是基于离散对数。 Schnorr数字签名主要工作不依赖于消息&#xff0c;生成签名过程与消息相关的部分需要进…

Blind Schnorr Signature

1. 引言 前序博客有&#xff1a; 盲签名 blind signature Blind Schnorr Signature交互签名Demo见&#xff1a; Blind Schnorr Signature Interactive Demo 参考资料 [1] Schnorr Applications: Blind Signatures

本体技术视点 | 为什么 BIP - 340 选择引入 Schnorr 签名算法?

引言 备受瞩目的技术升级 Taproot 软分叉将于最近激活&#xff0c;激活高度为 709632&#xff0c;距今已不足 500 个区块。此次升级包括三个改进提案&#xff0c;分别是 BIP - 340、BIP - 341 和 BIP - 342。其中&#xff0c;BIP - 340 引入了 Schnorr 签名&#xff0c;BIP - …

【密码学】Schnorr认证,Schnorr签名,安全性证明

Schnorr是Sigma协议的实例&#xff0c;从Schnorr 认证协议和Schnor签名两个部分来介绍。在前面关于认证协议的讲述中&#xff0c;用到了一些特定的符号&#xff0c;这里会继续使用。 首先认识Schnorr认证协议&#xff0c;定义如图所示 Schnorr认证协议和Schnorr签名方案的安全…

零知识证明系列之二——Schnorr协议

​Schnorr协议简介 Schnorr协议是由德国数学家和密码学家Claus-Peter Schnorr在1991年提出&#xff0c;是一种基于离散对数难题的知识证明机制。Schnorr本质上是一种零知识的技术&#xff0c;即Prover声称知道一个密钥x的值&#xff0c;通过使用Schnorr加密技术&#xff0c;可…

Schnorr 签名方案和 BLS 签名方案的全面对比

原文&#xff1a;https://medium.com/cryptoadvance/bls-signatures-better-than-schnorr-5a7fe30ea716https://medium.com/cryptoadvance/how-schnorr-signatures-may-improve-bitcoin-91655bcb4744 Schnorr 签名算法最初是由德国密码学家 Claus Schnorr 于 2008 年提出的&…

Schnorr签名算法(初始化和签名)C语言实现

Schnorr签名算法(初始化和签名) Schnorr签名算法(验证) Schnorr签名算法(正确性) Schnorr签名算法(举例) Schnorr签名算法(举例) C语言实例 #include <stdlib.h> #include <stdio.h> #include <time.h> int xy[22]; // 判断两个数是否互质 int isHuZhi(int …

Schnorr数字签名方案

Schnorr数字签名方案 Schnorr签名算法最初由德国密码学家claus schnorr于2008年提出&#xff0c;在密码学中&#xff0c;它是一种数字签名方案&#xff0c;以其简单著称 Schnorr数字签名方案也是基于离散对数的&#xff08;基于离散对数的还有ElGamal数字签名方案、DSA数字签…

记录我看的密码学方案中的技术,Shamir秘密共享,Schnorr零知识证明,EIGamal密码体制

记录我看的论文中基于的技术&#xff0c;对他们进行大概介绍 Shamir 秘密共享方案零知识证明EIGamal密码体制 Shamir 秘密共享方案 1979年&#xff0c;Shamir提出的一个基于拉格朗日插值的(k,n)门限方案 目的&#xff1a;可以将秘密s分给n个成员&#xff0c;规定至少有k&#…

schnorr签名和batch verification

schnorr 签名 概念&#xff1a;Schnorr签名算法最初是由德国密码学家ClausSchnorr于2008年提出的&#xff0c;在密码学中&#xff0c;它是一种数字签名方案&#xff0c;以其简单高效著称 原理&#xff1a;其安全性基于某些离散对数问题的难处理性。 签名过程&#xff1a; 和…

密码学学习笔记(十六 ):Schnorr签名算法

交互式零知识证明 零知识证明(ZKP)就是不会将证据泄露给验证者的知识证明。Schnorr身份认证识别协议是一个交互式ZKP&#xff0c;它满足了完备性、可靠性、零知识性。所谓的交互式ZKP方案通常包含3个步骤&#xff08;承诺、挑战和证明&#xff09;&#xff0c;在文献中通常被称…

ECDSA VS Schnorr signature VS BLS signature

1. ECDSA ECDSA&#xff0c;全称为Elliptic curve Digital Signature Algorithm&#xff0c;采用Elliptic curve cryptography来实现的数字签名算法。 公私钥对 ( p k , P ) (pk,P) (pk,P)&#xff0c;其中公钥 P p k G Ppk\times G PpkG&#xff0c; G G G为所选椭圆曲线的…

BSV 上的 Schnorr 签名

我们已经在 BSV 上实现了 Schnorr 签名。这是第一个也是唯一一个已知的实现&#xff0c;没有对原始协议进行任何更改。 一笔交易一个签名 Schnorr 是一种可以用于替代比特币签名当前使用的 ECDSA 算法的替代算法。一个关键优势是&#xff0c;同一交易的一个输入或多个输入中的多…

深入浅出零知识证明(一):Schnorr协议

最近在学习零知识证明&#xff0c;因为内容很多并且难度也大&#xff0c;想根据自己的学习路线做一系列总结&#xff0c;这是第一篇文章&#xff0c;主要介绍零知识证明的一些重要概念和思想&#xff0c;可以对零知识证明有直观的理解&#xff0c;然后讲解一个经典简洁的零知识…

密码学——Schnorr签名算法

一、基本知识 1.1 概述 Schnorr签名算法最初是由德国密码学家ClausSchnorr于2008年提出的&#xff0c;在密码学中&#xff0c;它是一种数字签名方案&#xff0c;以其简单高效著称&#xff0c;其安全性基于某些离散对数问题的难处理性。 1.2 椭圆曲线上的计算 密码学中&…

什么是 Schnorr 签名?

在密码学中&#xff0c;Schnorr 签名是由 Schnorr 签名算法生成的数字签名。 与大多数区块链不同&#xff0c;BTC自其早期以来基本保持不变&#xff0c;大多数升级都是有限的&#xff0c;并旨在增强网络的效率而不是功能。BTC协议的更新是非常罕见的&#xff0c;并且通常用于技…