【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

智能推荐

Hi3516A开发--编译内核、uboot_hi3516a_sdk_v1.0.5.0.tgz-程序员宅基地

文章浏览阅读1.5w次,点赞4次,收藏20次。有两种编译方式一、整个编译(1)编译整个osdrv目录:make OSDRV_CROSS=arm-hisiv300-linux all或者make OSDRV_CROSS=arm-hisiv400-linux all/* 如果单板使用spi接口nand flash作为存储介质,请在编译整个目录时传入如下FLASH_TYPE参数 */make OSDRV_CROSS=_hi3516a_sdk_v1.0.5.0.tgz

国内首个基于 Rust 语言的 RPC 框架 — Volo 正式开源!_rust开源项目-程序员宅基地

文章浏览阅读3k次。Volo 是字节跳动服务框架团队研发的轻量级、高性能、可扩展性强、易用性好的 Rust RPC 框架,使用了 Rust 最新的 GAT 和 TAIT 特性。在字节内部,Volo 已经落地多个业务和基础组件,并且取得了超预期的性能收益。..._rust开源项目

3.安装PHP环境(Ubuntu)_ubuntu离线安装php-程序员宅基地

文章浏览阅读516次。php环境 Ubuntu_ubuntu离线安装php

已知num为无符号十进制整数,请写一非递归算法,该算法输出num对应的r进制的各位数字。要求算法中用到的栈采用线性链表存储结构(1<r<10)。-程序员宅基地

文章浏览阅读74次。思路:num%r得到末位r进制数,num/r得到num去掉末位r进制数后的数字。得到的末位r进制数采用头插法插入链表中,更新num的值,循环计算,直到num为0,最后输出链表。//重置,s指针与头指针指向同一处。//更新num的值,至num为0退出循环。//末位r进制数存入s数据域中。//头插法插入链表中(无头结点)//定义头指针为空,s指针。= NULL) //s不为空,输出链表,栈先入后出。

开始报名!CW32开发者扶持计划正式进行,将助力中国的大学教育及人才培养_cw32开发者扶持计划申请-程序员宅基地

文章浏览阅读176次。武汉芯源半导体积极参与推动中国的大学教育改革以及注重电子行业的人才培养,建立以企业为主体、市场为导向、产学研深度融合的技术创新体系。2023年3月,武汉芯源半导体开发者扶持计划正式开始进行,以打造更为丰富的CW32生态社区。_cw32开发者扶持计划申请

希捷硬盘开机不识别,进入系统后自动扫描硬件以识别显示_st2000dm001不认盘-程序员宅基地

文章浏览阅读5.7k次。2014年底买的一块2TB希捷机械硬盘ST2000DM001-1ER164,用了两年更换了主板、CPU等,后来出现开机不识别的情况,具体表现为:关机后开机,找不到硬盘,就进入BIOS了,只要在BIOS状态下待机半分钟左右再重启,硬盘就会出现。进入系统后,重启(这个过程中主板对硬盘始终处于供电状态),也不会出现不识别硬盘的现象。就好像是硬盘或主板上某个电容坏了一样,刚开始给硬盘通电的N秒钟内电容未能..._st2000dm001不认盘

随便推点

HTML详解连载(7)-程序员宅基地

文章浏览阅读2k次,点赞57次,收藏59次。对伪元素和盒子模型进行了详细分析

PHP使用多线程-程序员宅基地

文章浏览阅读535次。PHP 5.3 以上版本,使用pthreads PHP扩展,可以使PHP真正地支持多线程。多线程在处理重复性的循环任务,能够大大缩短程序执行时间。  我之前的文章中说过,大多数网站的性能瓶颈不在PHP服务器上,因为它可以简单地通过横向增加服务器或CPU核数来轻松应对(对于各种云主机,增加VPS或CPU核数就更方便了,直接以备份镜像增加VPS,连操作系统、环境都不用安装配置),而是在于MySQL数..._php使用多线程

由excel一键生成json的小工具(基于python,仅支持单层嵌套)_excel转json github-程序员宅基地

文章浏览阅读1.9k次,点赞3次,收藏5次。最近空闲的时候做了点小游戏,小游戏开发过程中需要大量json处理,但是手动用文本编辑器调整json又不是很舒服,于是自己造了个由excel一键生成json的小工具,想到好久没发博客了,干脆传上来分享一下目录下载链接下载链接github(可以下载到py版本或exe版本):https://github.com/ZhChessOvO/basic_excel_to_json百度网盘(可以下载到exe版本):_excel转json github

mysql utf-8的作用_为什么不建议在MySQL中使用UTF-8-程序员宅基地

文章浏览阅读116次。作者:brightwang原文:https://www.jianshu.com/p/ab9aa8d4df7d最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value: ‘😃 我用的是UTF-8编码的客户端,服务器也是UTF-8编码的,数据库也是,就连要保存的这个字符串“????..._mysql utf8的作用

MATLAB中对多张图片进行对比画图操作(包括RGB直方图、高斯+USM锐化后的图、HSV空间分量图及均衡化后的图)_matlab图像比较-程序员宅基地

文章浏览阅读278次。毕业这么久了,最近闲来准备把毕设过程中的代码整理公开一下,所有代码其实都是网上找的,但都是经过调试能跑通的,希望对需要的人有用。PS:里边很多注释不讲什么意思了,能看懂的自然能看懂。_matlab图像比较

16.libgdx根据配置文件生成布局(未完)-程序员宅基地

文章浏览阅读73次。思路:  screen分为普通和复杂两种,普通的功能大部分是页面跳转以及简单的crud数据,复杂的单独弄出来  跳转普通的screen,直接根据配置文件调整设置<layouts> <loyout screenId="0" bg="bg_start" name="start" defaultWinId="" bgm="" remark=""> ..._libgdx ui 布局

推荐文章

热门文章

相关标签