RPC 开发系列一:RPC 基本介绍

2023-11-18

一、什么是 RPC?

        RPC 的全称是 Remote Procedure Call,即远程过程调用。

功能:

  • 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法;
  • 隐藏底层网络通信的复杂性,让我们更专注于业务逻辑。

二、RPC 通信流程

        发起调用请求的那一方叫做调用方,被调用的一方叫做服务提供方。RPC 一般默认采用 TCP 来传输。我们常用的 HTTP 协议也是建立在 TCP 之上的。

RPC 的通讯流程:序列化 --->  网络传输 ---> 反序列化

        数据格式的约定内容叫做“协议”。大多数的协议会分成两部分,分别是数据头和消息体。数据头一般用于身份识别,包括协议标识、数据大小、请求类型、序列化类型等信息;消息体主要是请求的业务参数信息和扩展属性等。

        更上一层楼,其中简化 API,屏蔽掉 RPC 细节,让使用方只需要关注业务接口也是关键(可以参考AOP 技术)。

        AOP 技术:采用动态代理的技术,通过字节码增强对方法进行拦截增强,以便于增加需要的额外处理逻辑。

  RPC 的通讯就变成流程:动态代理 ---> 序列化 --->  网络传输 ---> 反序列化 ----> 执行          

        RPC 是解决应用间通信的一种方式,而无论是在一个大型的分布式应用系统还是中小型系统中,应用架构最终都会从“单体”演进成“微服务化”,整个应用系统会被拆分为多个不同功能的应用,并将它们部署在不同的服务器中,而应用之间会通过 RPC 进行通信,可以说 RPC 对应的是整个分布式应用系统,就像是“经络”一样的存在

        RPC 框架能够帮助我们解决系统拆分后的通信问题,并且能让我们像调用本地一样去调用远程方法。利用 RPC 我们不仅可以很方便地将应用架构从“单体”演进成“微服务化”,而且还能解决实际开发过程中的效率低下、系统耦合等问题,这样可以使得我们的系统架构整体清晰、健壮,应用可运维度增强。当然 RPC 不仅可以用来解决通信问题,它还被用在了很多其他场景,比如:发 MQ、分布式缓存、数据库等。

        上面的图不能表达所有的情况,但是能说明 RPC 的框架。

        一句话概括: RPC 是我们最“熟悉的陌生人”。

三、设计协议

         这样整个协议就会拆分成两部分:协议头和协议体。

  1. 协议头:协议长度、序列化方式,还会放一些像协议标示、消息 ID、消息类型这样的参数。
  2. 协议体:接口方法、请求的业务参数值和一些扩展属性。

可以扩展的协议:

        整体协议就变成了三部分内容:固定部分、协议头内容、协议体内容,前两部分我们还是可以统称为“协议头”

四、序列化

        序列化就是将对象转换成二进制数据的过程,而反序列就是反过来将二进制转换为对象的过程。

常用的序列化

  • JDK 原生序列化
  • JSON
  • Hessian
  • Protobuf

如何选择序列化?

        首先可能想到的是性能和效率,还有空间开销,也就是序列化之后的二进制数据的体积大小。序列化协议的通用性和兼容性,序列化后的字节数据体积越小,网络传输的数据量就越小,传输数据的速度也就越快。 

 RPC 框架的过程中,构造入参、返回值对象,注意的问题:

  • 对象要尽量简单,没有太多的依赖关系,属性不要太多,尽量高内聚;
  • 入参对象与返回值对象体积不要太大,更不要传太大的集合;
  • 尽量使用简单的、常用的、开发语言原生的对象,尤其是集合类;
  • 对象不要有复杂的继承关系,最好不要有父子类的情况。

五、网络通讯

网络 IO 模型:

  • 同步阻塞 IO(BIO)
  • 同步非阻塞 IO(NIO)
  • IO 多路复用
  • 异步非阻塞 IO(AIO)

最常用的就是同步阻塞 IO 和 IO 多路复用。

同步阻塞 IO:

        应用进程发起 IO 系统调用后,应用进程被阻塞,转到内核空间处理。之后,内核开始等待数据,等待到数据之后,再将内核中的数据拷贝到用户内存中,整个 IO 处理完毕后返回进程。最后应用的进程解除阻塞状态,运行业务逻辑。这里我们可以看到,系统内核处理 IO 操作分为两个阶段——等待数据和拷贝数据。

IO 多路复用:

         多路就是指多个通道,也就是多个网络连接的 IO,而复用就是指多个通道复用在一个复用器上。当用户进程调用了 select,那么整个进程会被阻塞。同时,内核会“监视”所有的 socket,当任何一个 socket 中的数据准备好了,select 就会返回。这个时候用户进程再调用 read 操作,将数据从内核中拷贝到用户进程。

什么是零拷贝?

        所谓的零拷贝,就是取消用户空间与内核空间之间的数据拷贝操作。零拷贝有两种解决方式,分别是 mmap+write 方式和 sendfile 方式,mmap+write 方式的核心原理是通过虚拟内存来解决的。

五、动态代理

Spring AOP:

        就是采用动态代理技术,通过对字节码进行增强,在方法调用的时候进行拦截,以便于在方法调用前后,增加我们需要的额外处理逻辑 。

参考:https://www.cnblogs.com/joy99/p/10941543.html

        RPC 会自动给接口生成一个代理类,当我们在项目中注入接口的时候,运行过程中实际绑定的是这个接口生成的代理类。这样在接口方法被调用的时候,它实际上是被生成代理类拦截到了,这样我们就可以在生成的代理类里面,加入远程调用逻辑。

动态代理可以从这样三个角度去考虑:

  • 生成的字节码越小,运行所占资源就越小。
  • 以每次调用接口方法的时候,都执行生成的代理类,这时生成的代理类的执行效率就需要很高效。
  • 选择一个使用起来很方便的代理类框架:API 设计是否好理解、社区活跃度、还有就是依赖复杂度等等。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RPC 开发系列一:RPC 基本介绍 的相关文章

  • Apache Avro 文档概况

    文章主题来源于英文源文档 gt Apache Avro 1 11 0 文档 Apache Avro 1 11 0 Documentation 1 介绍 Apache Avro 是一个数据序列化 data serialization 框架 A
  • Golang RPC性能测试

    最近刚好要使用Golang的RPC 因此对Golang标准库的RPC进行了一下测试 看看其性能到底如何 RPC服务端和客户端的实现完全使用RPC的net rpc标准库 没有经过特殊的优化 主要针对下面三个场景进行测试 测试之前需要先说明一下
  • 使用RPC对某者web端骑行数据进行爬取

    使用RPC技术hook web端JS 骑行app某者web端爬虫 2022 2 1 获取轨迹ID 通过更改年月 可以发现获取每个月轨迹ID 的方式 这个非常简单 只需要拷贝请求头headers就可以直接获取 2 获取轨迹详情 可以发现三个请
  • go grpc环境安装

    1 安装protoc编译器 protoc可执行文件用于编译 protocolbuf proto文件 和 protobuf 运行时 它是 C 写的 其可以将proto文件翻译为指定语言的代码 比较简单的安装方式是直接下载编译好的二进制文件 仓
  • go 进阶 go-zero相关: 七. 拦截器与熔断拦截器

    目录 一 拦截器的基础使用 1 服务端拦截器 2 客户端拦截器 二 拦截器底层底层执行原理 三 go zero默认添加的拦截器 客户端 1 熔断器拦截器 BreakerInterceptor 服务端 一 拦截器的基础使用 在go zero
  • 套接字异常:“端点映射器没有更多可用端点”

    我正在使用winsock 和C 来设置服务器应用程序 我遇到的问题是调用listen导致第一次机会异常 我想通常这些可以被忽略 但我发现其他人也有同样的问题 它导致应用程序偶尔挂起 任何帮助将不胜感激 第一个机会例外是 0x 1234567
  • REST 与 JSON-RPC? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我正在尝试在 REST 和 JSON RPC 之间进行选择来为 Web 应用程序开发 API 他们如何比较 2015 年更新 我发现 REST 更容易开发和用于在 Web HTTP 上提供
  • 如何在客户端-服务器 PlayN 游戏中处理 RPC?

    我想使用 PlayN 创建客户端 服务器纸牌游戏 例如心 虽然我主要关注 HTML5 输出 但我希望与输出平台无关 以防我将来决定制作 Android 客户端 我应该如何处理RPC机制 这些是我想到的选项 通过 get post 方法将 J
  • 如何通过 RPC 连接到 Hedera 测试网?​

    我无法通过 HTTP 连接到 Hedera Testnet RPC 端点 可靠地 我间歇性地收到以下 未知错误 Request ID fe7b9928 a23f 0d72 61a1 b7cd23658c01 Unknown error in
  • GoLong的学习之路,进阶,微服务之使用,RPC包(包括源码分析)

    今天这篇是接上上篇RPC原理之后这篇是讲如何使用go本身自带的标准库RPC 这篇篇幅会比较短 重点在于上一章对的补充 文章目录 RPC包的概念 使用RPC包 服务器代码分析 如何实现的 总结 Server还提供了两个注册服务的方法
  • 至多一次和恰好一次

    我正在研究分布式系统 当涉及到 RPC 部分时 我听说过这两种语义 最多一次和恰好一次 据我所知 当我们不希望重复执行时 最多一次用于数据库实例 第一个问题 这是如何实现的 服务器如何知道它不应该再次执行该请求 它可能是重复的 但也可能是合
  • GWT (2.4.0) + XSRF

    我一直在尝试让 XSRF 在网络应用程序上运行 但没有成功 我正在研究一个典型的登录实现 我正在关注谷歌的代码 https developers google com web toolkit doc latest DevGuideSecur
  • 如何在java中使用RabbitMQ实现RPC机制

    如何在java中使用RabbitMQ实现RPC机制 生产者和消费者 我也访问官方网站http www rabbitmq com api guide html rpc http www rabbitmq com api guide html
  • Invoke-Command 和直接查询的区别

    我目前正在编写一个从服务器查询磁盘信息的脚本 我遇到了一个问题 我真的不知道这里发生了什么 愿你能帮助我 以下代码有效 已替换 ComputerName space1 Invoke Command ComputerName xxxxxx S
  • 在 Java 中伪造堆栈跟踪

    当您在 Java 中使用 RMI 时 异常的远程堆栈跟踪将在您收到异常时添加到前面 有点像这样 ERROR Client received error when doing stuff myapp FooBarException bla a
  • 用于远程IP(主机)的Java RMI

    我是新手 我无法理解RMI正确 互联网上有大量的教程 但据我所知 它们都是针对本地主机的 服务器和客户端都运行在同一台机器上 我想在任何机器上运行客户端 并且主机将位于一台计算机上 让我们考虑一下IP 11 11 11 11 上1099 但
  • Hedera 上几乎相同的交易中“gasUsed”值存在巨大差异 - 为什么?

    我注意到所使用的气体量之间存在差异 通过交易几乎是相同的 我正在调用智能合约 连续两次使用相同的参数 两者之间的唯一区别 是我正在设置gasLimit到精确值 由返回eth estimateGas在第一个中 我正在设置gasLimit to
  • 没有代理/存根 DLL 的进程外 COM 服务器?

    我正在学习如何实现进程外 COM 服务器 并发现了这篇代码项目文章 构建本地 COM 服务器和客户端 分步示例 http www codeproject com Articles 8679 Building a LOCAL COM Serv
  • 远程过程调用认证

    我正在使用远程过程调用 RPC 在本地计算机上通信数据 我的要求是使用 RPC 在两个处理之间通信数据 但服务器应该通过某种方式对客户端进行身份验证 我遇到了 RpcBindingSetAuthInfo 它设置身份验证和授权信息 第四个参数
  • 同步 gRPC 客户端同步/异步服务器

    我只是好奇 异步 gRPC 服务器是否支持多个客户端的连接 如果不是 异步的可以吗 以及异步服务器 同步客户端的组合 甚至可能吗 是的 同步 gRPC 支持开箱即用的多个连接客户端 我亲自测试了多达 2000 个同时连接的客户端到一个用 G

随机推荐