【RPC】RPC基本介绍-程序员宅基地

技术标签: Java  RPC  rpc  

0. RPC是什么

RPC(Remote Procedure Call)叫作远程过程调用,它是利用网络从远程计算机上请求服务,可以理解为把程序的一部分放在其他远程计算机上执行。通过网络通信将调用请求发送至远程计算机后,利用远程计算机的系统资源执行这部分程序,最终返回远程计算机上的执行结果。


1. RPC的核心组成部分

PRC主要设计五个部分:

  • user(服务调用方)
  • user-stub(调用方的本地存根)
  • RPCRuntime(RPC通信者)
  • server-stub(服务端的本地存根)
  • server(服务端)

服务调用方、调用方的本地存根及其一个RPC通信包的实例存在于调用者的机器上;而服务提供方、服务提供方的存根及另一个RPC通信包的实例存在于被调用的机器上。


1.1 服务调用方(Consumer)

服务调用方也叫服务消费者,它的职责之一是提供需要调用的接口的全限定名和方法,调用方法的参数给调用端的本地存根;职责之二是从调用方的本地存根中接收执行结果。


1.2 服务提供方(Provider)

服务提供方就是服务端,它的职责就是提供服务,执行接口实现的方法逻辑,也就是为服务提供方的本地存根提供方法的具体实现。


1.3 本地存根(stub)

在远程调用中,对于Consumer发起的函数调用,Provider如何精准的直到自己应该执行哪个函数呢?

这就需要stub了。Stub的存在就是为了让远程调用像本地调用一样直接进行函数调用,无须关系地址空间隔离、函数不匹配等问题。

Stub的职责就是进行类型和参数转化。

本地存根分为服务调用方的本地存根和服务提供方的本地存根。

服务调用方的本地存根和服务消费者都属于Consumer端,它们存在于同一台机器上,服务调用放的本地存根会接收Consumer的函数调用,本地存根会解析函数调用的函数名、参数等信息,整理并且组装这些数据,然后将这些数据安装定义好的协议进行序列化,打包成可传输的消息,交给RPCRuntime(RPC通信者)。服务调用方的本地存根除了会处理服务消费者提供的方法、参数、方法参数类型等数据,还会处理服务提供方返回的结果,它会将RPCRuntime返回的数据反序列化成服务调用方所需要的数据结果并传递给服务消费方。

从服务消费方的角度来看,Stub隐藏了远程调用的实现细节,就像是远程服务的一个代理对象,可以让服务消费方感觉调用远程服务方法就像调用本地方法一样。

服务提供方的本地存根与服务提供方都属于Provider端,它们一起存在于同一台机器上。当Provider端的RPCRuntime收到请求包后,交由服务提供方的本地存根进行参数等数据的转化。服务提供方的本地存根会重新转换客户端传递的数据,以便在Provider端的机器上找到对应的函数,传递正确的参数数据,最终正确地执行真实函数的调用。等函数执行完成后,服务提供方会将执行结果返回给服务提供方的本地存根,由本地存根再将结果数据序列化、打包,最后交给RPCRuntime。服务提供方的本地存根与服务调用方的本地存根一样都是充当了翻译员的角色。


1.4 RPC通信者(RPCRuntime)

RPCRuntime负责数据包的重传,数据包的确认、数据包路由和加密等。

在Consumer端和Provider端都会有一个RPCRuntime实例,负责双方之间的通信,可靠地将存根船渡地数据包传输到另一端。



2. RPC调用过程

RPC调用过程可以分为四个阶段,分别是服务暴露过程、服务发现过程、服务引用过程和方法调用过程。

2.1 服务暴露的过程

服务暴露又称服务导出,服务导出的叫法相对于服务暴露更加形象一些。服务暴露发生在Provider端。

根据服务是否暴露到远程可以分为两种,一种是服务只暴露到本地,另一种则是暴露到远程。

  • 服务只暴露在本地:在一台机器上,一个应用服务可以认为是机器上的一个进程,当该进程启动后,如果不进行服务暴露,那么该进程不会绑定一个端口用于监听和接收Consumer端的连接和请求,反之,该进程会监听本地的端口。绑定并且监听本地端口的动作则是由前面提到的RPCRuntime完成的。比如一个Dubbo服务,默认的协议端口是20880,当进程启动后,应用服务进程会监听20880端口。当应用进程准备好所有应该暴露的服务并且完成端口的绑定和监听后,服务暴露到本地的过程也随之结束。
  • 暴露到远程:其中的远程其实是指有一个统一的管理中心来管理所有应用服务的地址和服务信息,这个统一的管理中心就是注册中心(Registry)。应用服务暴露到远程的第一步也是在本地绑定端口,过程与暴露到本地一模一样,但是当本地端口绑定完成后,还需要将Provider端的应用服务信息注册到注册中心

在这里插入图片描述Provider端的应用服务信息包括Provider端的地址、端口、应用服务需要暴露的接口定义信息等。Provider 端除了会在应用服务启动的时候将服务信息注册到注册中心,还会与注册中心保持心跳保活如果Provider端某个节点异常下线,注册中心在一段时间的保活检查后,就会将该节点的信息从注册中心中移除,防止Consumer端把请求发送到该下线的节点上。因为业务迭代迅速,服务端的服务变动及上下线很频繁,通过注册中心管理服务的地址信息可以让客户端动态地感知服务变动,并且客户端不需要再显式地配置服务端地址,只要配置注册中心地址即可,而注册中心集群一般不会变动。注册中心的内容会在后续更新介绍。


2.2 服务发现的过程

服务发现的过程发生在(Consumer)端,服务发现的过程也就是寻址的过程,Consumer端如果要发起RPC调用,则需要先知道自己想要调用的应用服务有哪些服务提供者,也就是需要知道这些服务提供者的地址和端口。

服务发现的方式有两种,分别是直连式和注册中心式,对应的是Provider端的两种服务暴露方式。

  • 直连式:服务消费者可以根据服务暴露的地址和端口直接连接远程服务,但是每次服务提供者的地址和端口变更后,服务消费者都需要随之变更配置的地址和端口。这种方式不建议在生产环境中使用,更多被用来做服务测试。而且直连式不适合服务治理。如果Provider端的应用服务仅仅暴露在本地,则Consumer端只能通过直连式来做服务发现。
  • 注册中心式:服务消费者通过注册中心进行服务发现。也就是服务提供者的地址和端口从注册中心获取。当服务提供者变化时,注册中心能够通知服务消费者有关服务提供者的变化。如果Provider端采用暴露到远程的方式暴露服务,则Consumer端可以选择直连式和注册中心式进行服务发现。

2.3 服务引用的过程

服务引用的过程发生在服务发现之后,当Consumer端通过服务发现获取所有服务提供者的地址后,通过负载均衡策略选择其中一个服务提供著的节点进行服务引用。服务引用的过程就是与某一个服务节点建立连接,以及在Consumer端创建接口的代理的过程其中建立连接也就是两端的RPCRuntime 建立连接的过程。


2.4 方法调用的过程

当服务引用完成后,Consumer端与Provider端已经建立了连接,可以进行方法的调用。

在这里插入图片描述

(1)服务消费者以本地调用方式(即以接口的方式)调用服务,它会将需要调用的方法、参数类型、参数传递给服务消费方的本地存根。

(2)服务消费方的本地存根收到调用后,负责将方法、参数等数据组装成能够进行网络传输的消息体(将消息体对象序列化为二进制数据),并将该消息体传输给RPC通信者。

(3)Consumer 端的RPC通信者通过sockets 将消息发送到Provider端,由Provider端的RPC通信者接收。Provider端将收到的消息传递给服务提供方的本地存根。

(4)服务提供方的本地存根收到消息后将消息对象反序列化。

(5)服务提供方的本地存根根据反序列化的结果解析出服务调用的方法、参数类型、参数等信息,并调用服务提供方的服务。

(6)服务提供方执行对应的方法后,将执行结果返回给服务提供方的本地存根。

(7)服务提供方的本地存根将返回结果序列化,并且打包成可传输的消息体,传递给Provider端的RPC通信者。

(8) Provider端的RPC通信者通过sockets将消息发送到Consumer端,由Consumer端的RPC通信者接收。Consumer端将收到的消息传递给服务消费方的本地存根。

(9)服务消费方的本地存根收到消息后将消息对象反序列化。反序列化出来的是方法执行的结果,并将结果传递给服务消费者。

(10)服务消费者得到最终执行结果。

服务暴露、服务发现、服务引用和方法调用这四个阶段组成了整个RPC的执行过程。


下面举一个例子来将这四个阶段连接起来。

现在有一个订单服务应用,其中订单服务提供了查询订单等方法。现在需要将该订单服务部署在三个节点上,分别是节点A、节点B和节点C。除了订单服务,还有一个用户服务,用户服务内的一个查询订单的功能需要调用订单服务的查询订单方法。所以这里的订单服务就是服务提供方,而用户服务就是服务消费方。订单服务每在一个节点上完成部署后,该节点的信息都会被注册到注册中心。当用户服务启动时,知道该服务依赖订单服务,所以会先从注册中心执行服务发现的过程,发现订单服务有三个节点提供服务,选择其中一个节点后,与该节点建立连接。当用户发起查看订单的请求时,用户服务会向该节点发送需要调用的方法信息,也就是查询订单方法的方法名、参数类型、参数等。等订单服务执行完成后将结果返回给用户服务,这个过程中订单服务与用户服务之间的连接一直保持活跃。当订单服务的该节点下线时,注册中心通知用户服务该节点已下线,当下次用户服务又发起对订单服务的调用时会选择另一个节点建立连接,并且发送调用请求,这就是远程过程调用的全部过程。

参考资料:《深入理解RPC框架原理与实现》 华钟明著.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Aibiabcheng/article/details/125288272

智能推荐

Linux字符设备驱动框架之IIC总线驱动框架_linux iic 设备是字符设备吗-程序员宅基地

文章浏览阅读621次。目录1、I2C简介2、I2C驱动框架2.1、I2C核心2.1.1、I2C bus初始化2.1.2 IIC核心提供的接口函数2.2 IIC总线驱动2.2.1 I.MX6U 的 I2C 适配器驱动分析2.3、IIC设备驱动2.3.1、I2C设备驱动解析2.3.2、I2C 设备驱动编写流程1、i2c设备信息描述2、i2c设备数据收发处理流程2.3.3、I2C设备驱动实例1、参考链接:https://www.cnblogs.com/linfeng-learning/p/9523046.html#_label22_linux iic 设备是字符设备吗

zynq使用lwip远程更新flash_zynq lwip-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏13次。1.目的zynq通过使用以太网实现远程更新flash,同时实现不断电重启,方便用户升级2.硬件环境vivado2018.2使用zynq7开发板zedboard,只需要搭建最小系统包括以太网、uart、flash控制器、ddr3.软件环境搭建硬件环境后,生成bit,导出到sdk该测试环境基于echo模板改动4.软件说明新增qspi_remote_update.h新增qspips...._zynq lwip

Python:在CMD窗口中调用python函数_cmd调用python函数-程序员宅基地

文章浏览阅读3w次,点赞18次,收藏28次。有时我们会需要在其他语言的环境下调用python,对不同的语言都有各自的方法。本文主要以CMD为例说明如何使用命令行运行某一个py文件下面的一个函数,主要使用如下代码:python -c "function_name(args)"这其中主要有两种情况:A.Python文件中只包含一个函数,而且不需要输入任何参数例如a.py为如下:print('hello world')........._cmd调用python函数

tsconfig.json 配置 update `jsx: “react“` into `jsx: “react-jsx“`终端警告_warn [warn] update `jsx: "react"` into `jsx: "reac-程序员宅基地

文章浏览阅读3.6k次。使用 umiJS 时出现的终端警告:WARN [WARN] update jsx: "react" into jsx: "react-jsx" to suport the new JSX transform in React 17 in tsconfig.json解决方法:确保 typescript 的依赖安装完成,随便打开一个提示错误的 .tsx 文件。macOS 使用 command + shift + p,Windows 貌似是 ctrl + shift + p。然后输入 TypeScri_warn [warn] update `jsx: "react"` into `jsx: "react-jsx"` to suport the new

利用Selenium控制网页内嵌滚动条_selenium 页面嵌套一个小页面 都有滚动-程序员宅基地

文章浏览阅读8.9k次,点赞7次,收藏35次。利用Selenium控制网页内嵌滚动条_selenium 页面嵌套一个小页面 都有滚动

UART串口IAP下载电路及BOOTLOADER分析_iap15下载口电路-程序员宅基地

文章浏览阅读1.6k次,点赞2次,收藏3次。针对正点原子的开发板上串口IAP下载电路进行的分析关于BOOTLOADER在STM32芯片出厂时,官方已经在片上系统存储器中固化好bootloader程序,这是使用串行外设(USART,CAN,USB,I2C等)将用户的APP下载到内部FLASH中.bootloader程序主要功能使用嵌入式串行接口按照预定义的通信协议下载代码可传送并更新 Flash 代码、数据和向量表部分BOO..._iap15下载口电路

随便推点

image_transport Documentation_image_transport::camerapublisher-程序员宅基地

文章浏览阅读256次。http://docs.ros.org/api/image_transport/html/Code APIWhen transporting images, you should use image_transport’s classes as drop-in replacements for ros::Publisher and ros::Subscriber.image_transpor..._image_transport::camerapublisher

Phoenix 对HBASE表操作_phoenix column_encoded_bytes=0 的作用-程序员宅基地

文章浏览阅读462次。https://www.yuque.com/docs/share/c0b81507-2318-48a7-a22c-2278b0e82ab9?# 《01.对HBase表操作》_phoenix column_encoded_bytes=0 的作用

基于javaweb+mysql的jsp+servlet校园疫情防控管理信息系统疫情播报系统(java+servlet+jsp+bootstrap+mysql+css)-程序员宅基地

文章浏览阅读306次,点赞8次,收藏10次。基于javaweb+mysql的jsp+servlet校园疫情防控管理信息系统疫情播报系统(java+servlet+jsp+bootstrap+mysql+css)基于javaweb的JSP+Servlet校园疫情防控管理信息系统疫情播报系统(java+servlet+jsp+bootstrap+mysql+css)有了此系统,大大方便了学校疫情的防控工作,加大了学校疫情防控的力度,提高学校疫情防控的效率,尽最大地可能避免学校出现新冠肺炎疫情。课程设计,大作业,毕业设计,项目练习,学习演示等。

「网络安全」SQL注入攻击的真相_1、在网络上找一个网站,研究sql注入攻击的可能性。-程序员宅基地

文章浏览阅读128次。「网络安全」SQL注入攻击的真相_1、在网络上找一个网站,研究sql注入攻击的可能性。

Springboot的问题 Mybatis之 java.lang.ClassCastException: com.cra.pojo.User cannot be cast to java.lang._java.lang.classcastexception: class com.springboot-程序员宅基地

文章浏览阅读351次。我们首先获得前端传递过来的数据,然后传递到数据库当中进行验证,这个问题是由于 mybatis中返回数据类型的问题导致的。这个时候就可以得到返回的int行来判断是否数据库中存在数据。如果使用 User类作为返回对象的话,就会出现以上问题。众所周知,数据库会返回 记录条数。但是mybatis不会返回记录条数。比如我们在验证用户登录时,_java.lang.classcastexception: class com.springbootjsp.pojo.backend_user cann

ubuntu22.04遇到google浏览器的显示问题_ubuntu浏览器不显示文字和图片-程序员宅基地

文章浏览阅读548次。解决google浏览器显示不全的问题_ubuntu浏览器不显示文字和图片

推荐文章

热门文章

相关标签