RPC介绍

目录

介绍

区别

普通网络通信

RPC

一次rpc过程

从涉及到的角色来看

总结

RPC的功能实现

服务寻址功能

引入

本地调用

远程调用

确定实例

确定函数

解决方法

服务实例定位

静态配置

服务发现机制

客户端发现

服务端发现

函数定位

序列化和反序列化功能

介绍

必要性

网络传输功能

过程

协议

TCP和HTTP对比


介绍

RPC(Remote Procedure Call) 远程过程调用,是一种通过网络从远程计算机程序上请求服务的一种调用模型

  • 利用该思想,可以让不同的服务间方法调用就像本地调用一样便捷,且不需要了解底层网络技术
  • 简单来说,就是让A服务器上的a服务可以很方便地和B服务器上的b服务通信

看似高大上,其实它的底层流程和普通的网络通信(一个客户端通过 socket 发送数据、服务端接收并返回结果)差不多

但为什么会有RPC这样一个独立的概念?

  • 核心区别不在于"是否用 socket 传输",而在于 抽象层次

区别

普通网络通信

开发者需要自己决定 消息格式 (怎么组织请求和响应)、序列化方式 (json/binary)、协议细节 (TCP/UDP/HTTP),以及在合适的地方进行网络传输(socket 读写)

RPC

RPC 的目标就是 让远程调用看起来像本地函数调用 ,所以它把网络通信这一堆繁琐的细节隐藏在 Stub(存根) 层里

一次rpc过程

历经了一次完整的网络请求)

  • 客户端调用时 :写的是 result = add(3,5) -- 背后实际上:由Stub 把函数名+参数序列化后通过 socket 发出去

  • 服务端收到时 :Stub 解析消息,找到对应的函数 add,调用本地实现,把结果再打包返回

  • 客户端拿到结果:Stub 反序列化结果,交给调用方(就像函数返回值一样)

从涉及到的角色来看

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

总结

  • 它的底层实际上就是普通网络通信
  • 但 RPC 之所以叫 "RPC",是因为它把 底层网络通信 封装成了 函数调用,实现了"透明调用"的语义

RPC的功能实现

主要分为服务寻址、序列化和反序列化、网络传输功能三部分

服务寻址功能

引入

本地调用

只有一个上下文,符号表和函数体都在同一个地址空间,只要知道函数指针,就能跳转到函数体执行

远程调用

涉及到跨进程/跨主机,需要知道在哪台机器?哪个进程? 哪个函数?

确定实例

分布式系统里,同一个服务通常会有多个实例:

  • 可能在不同机器上(IP 不同)

  • 可能在同一机器的不同进程里(端口不同)

确定函数

在远程调用中,不同服务的地址空间不同,函数指针在另一台机器上没意义

  • 即使两个进程在同一机器上,它们的虚拟地址空间也是隔离的,函数地址依然无用
  • 因此,远程调用不能直接传递函数指针

解决方法

服务实例定位
静态配置

如果实例固定,可以在表中写死ip+端口,直接映射

服务发现机制

如果实例会变动(弹性扩/缩容、故障下线),就需要引入中介 -- 注册中心

  • 保存当前可用的服务实例列表

服务发现分为两种模式,客户端发现(Client-side discovery)和 服务端发现(Server-side discovery / Load-balancer / API Gateway)

  • 两者本质的区别,是在 "由谁来做负载均衡(选择实例)"上
客户端发现

客户端向注册中心查询 某服务的所有实例 ,由客户端本地使用某种负载均衡算法选择一个实例,直接发请求

优点

  • 可以直接请求到目标实例,延迟小
  • 负载均衡负担分散到各个客户端
  • 客户端灵活

缺点

  • 每个客户端(不同语言/框架)都要实现 discovery(服务发现) + LB(负载均衡)
  • 如果客户端数量极大,注册中心会承受大量查询压力
  • 客户端通常会缓存实例列表,以降低注册中心负载,若缓存 TTL 或更新机制不好,会出现短暂 stale(调用已经下线的实例或错过新实例)
服务端发现

客户端请求统一入口入口组件从注册中心获取实例列表,选择一个并转发请求

优点

  • 入口(LB/Proxy)可以做集中优化,在高并发场景下能更好地控制连接
  • 可以在入口层做集中限流、熔断、路由规则,易于横向扩展入口层

缺点

  • 多一跳,入口层可能成为额外的延迟来源(转发/队列/排队)
函数定位

为了解决函数地址失效的问题,RPC 引入 **方法 ID(Call ID)--**所有函数都有自己的一个ID,在所有进程中都唯一

  • 客户端在做远程过程调用时会查表,找出调用方法对应的Call ID,然后传给服务端
  • 服务端也会查表,找到对应的函数指针,然后执行相应函数的代码

序列化和反序列化功能

介绍

序列化:将消息对象转换为二进制流

反序列化:将二进制流转换为消息对象

必要性

本地调用中,只需要将数据压入栈中,然后让函数去栈中读取即可

远程调用涉及到数据的传输

  • 由于客户端和服务端不在同一个服务器上,涉及不同的进程,不能通过内存传递参数
  • 此时就需要让客户端先将请求参数转成字节流(编码),传递给服务端,服务端再将字节流转为自己可读取格式(解码),这就是序列化和反序列化的过程
  • 反之,服务端返回值也逆向经历序列化和反序列化到客户端

(其实也就是网络传输的必要手段)

网络传输功能

过程

客户端将Call ID和序列化后的参数字节流传输给服务端,服务端执行调用逻辑后,将序列化后的调用结果回传给客户端

协议

主要有TCP、UDP、HTTP协议

(这块就不细说了,就是计网那些东西)

TCP和HTTP对比

基于TCP协议实现的RPC调用

  • 直接在传输层上自定义协议
  • 可以更灵活地对协议字段进行定制,更小的协议开销,可实现更高的性能和吞吐量
  • 实现复杂,需要处理粘包、拆包、心跳、超时等问题,维护成本高

基于HTTP协议实现的RPC调用

  • 在应用层使用 HTTP 作为传输载体
  • 实现简单,跨语言兼容性强
  • 协议封装层次多,头部开销大,传输效率略低于纯 TCP
相关推荐
余辉zmh3 小时前
【C++篇】:ServiceBus RPC 分布式服务总线框架项目
开发语言·c++·rpc
OAFD.3 小时前
YOLOv3 详解:核心改进、网络架构与目标检测实践
网络·yolo·目标检测
鹿鸣天涯4 小时前
商用密码应用安全性评估
网络·安全·web安全
迎風吹頭髮4 小时前
Linux服务器编程实践27-详解TCP状态转移:从LISTEN到TIME_WAIT的完整路径
linux·服务器·网络
你好,赵志伟4 小时前
网络层(IP)
网络·ip
9527出列5 小时前
Netty源码分析--客户端连接接入流程解析
网络协议·netty
Jtti5 小时前
SSH连接服务器超时?可能原因与解决方案
服务器·网络·php
L47546 小时前
SSL/TLS证书:保障网站安全的关键
网络协议·安全·ssl·tls
deng-c-f6 小时前
Linux C/C++ 学习日记(27):KCP协议(三):源码分析与使用示例
linux·服务器·网络·c++·网络编程·kcp