手动实现简易版RPC(上)

news2025/2/26 18:46:29

手动实现简易版RPC(上)

前言

什么是RPC?它的原理是什么?它有什么特点?如果让你实现一个RPC框架,你会如何是实现?带着这些问题,开始今天的学习。

本文主要介绍RPC概述以及一些关于RPC的知识,为后面实现做充足的准备。


1. RPC简述

1.1 什么是RPC

专业定义: RPC是远程过程调用(Remote Procedure Call)。 RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制,让使用者不必显式的区分本地调用和远程调用。

举个🌰:

假设你住在一个大社区里,社区里有很多居民,每个人都有自己的专长。比如,有的擅长修理电器,有的擅长烹饪美食,还有的擅长园艺。有一天,你突然发现家里的水龙头坏了,你并不会修理,于是你想到社区里那位擅长修理电器的居民。

在这个场景下,你可以将自己想象成客户端(Client),那位擅长修理的居民则是服务端(Server)。你想要调用服务端的“修理水龙头”这个“方法”。但是,你和服务端并不在同一个地方,不能直接交流,于是你需要通过一些方式(比如电话,发短信,或者社区的信息平台)来发起这个调用请求。

而达成的效果呢:就像你自己修理水龙头一样的丝滑,你不需要知道整个修理的过程,你只需要知道,修理好了这个结果就行

1.2 为什么要用RPC

回到 RPC 的概念,RPC 允许一个程序(称为服务消费者)像调用自己程序的方法一样,调用另一个程序(称为服务提供者)的接口,而不需要了解数据的传输处理过程、底层网络通信的细节等。这些都会由 RPC 框架帮你完成,使得开发者可以轻松调用远程服务,快速开发分布式系统。

举个🌰:

现在有项目A和项目B两个单独的项目,项目A提供一系列的关于宠物的服务,然后项目B也想使用项目A 的一些服务,完成宠物信息的查询。

项目A的查询猫咪信息的服务接口伪代码如下:

interface CatService {
    /***
     * 获取猫咪信息
     * @return
     */
    Cat getCat(参数1,参数2...);


    /***
     * 按照id获取猫咪信息
     * @param id
     * @return
     */
    Cat getCatById(int id);
    
    //....other
}

如果没有RPC,项目B会如何调用项目A的服务呢?

首先,由于项目A和项目 B都是独立的系统,不能像 SDK一样作为依赖包引入。

那么就需要项目 A提供 web 服务,并且编写一个点餐接口暴露服务,比如访问http:localhost:8088/api/cat 就能调用服务A的猫咪查询服务;然后项目B作为服务消费者,需要自己构造请求,并通过 HttpClient 请求上述地址,拿到相关信息。

如果项目B需要调用更多第三方服务,每个服务和方法的调用都编写一个 HTTP 请求,那么会非常麻烦

示例伪代码如下:

url="http:localhost:8088/api/cat"
req=new Req(参数1,参数2,参数3)
res=httpClient.post(url).body(reg).execute()
cat =res.data

那么如果使用RPC框架,对于项目B来说,要实现上述调用,可能只需要一行代码

cat=CatService.getCat(参数1,参数2,参数3)

看起来是不是和调用自己的方法一样,十分简洁。

2.RPC设计实现思路

基本设计

RPC框架为什么能够简化调用?该如何实现一个RPC框架呢?带着这两个问题,一起往下看

首先呢,我们将上述服务A抽象为服务提供者(producer),服务B抽象为服务消费者(consumer)

请添加图片描述

消费者想要调用提供者,就需要提供者启动一个 web 服务 ,然后通过 请求客户端 发送 HTTP 或者其他协议的请求来调用。
比如请求 http:localhost:8088/api/cat 地址后,提供者会调用 CatService的 getCat方法:

请添加图片描述

但如果提供者提供了多个服务和方法,每个接口和方法是不是都要单独写一个接口?消费者需不需要针对每个接口写一段 HTTP 调用的逻辑么?

其实可以提供一个统一的服务调用接口,通过请求处理器,根据客户端的请求参数来进行不同的处理、调用不同的服务和方法。

可以在服务提供者程序维护一个本地服务注册器,记录服务和对应实现类的映射。

举个🌰:

消费者要调用 CatService服务的 getCat 方法,可以发送请求,参数为 service=CatService,method=getCat 然后请求处理器会根据 service 从服务注册器中找到对应的服务实现类,并且通过 Java 的反射机制调用 method 指定的方法。

请添加图片描述

但是在数据传输过程中是不支持java实体类进行传输的,所以为了达成网络传输,需要对传输的参数等实现序列化和反序列化

请添加图片描述

为了简化消费者发请求的代码,实现类似本地调用的体验。可以基于代理模式,为消费者要调用的接口生成一个代理对象,由代理对象完成请求和响应的过程。所谓代理,就是有人帮你做一些事情,不用自己操心。
至此,一个最简易的 RPC 框架架构图诞生了,下图中的虚线部分:

请添加图片描述

整个简单的调用过程客以参考下图

请添加图片描述

拓展设计

虽然上述设计已经跑通了基本调用流程,但离一个完备的 RPC 框架还有很大的差距,让我们带着问题来进一步完善一下架构设计。

1、服务注册发现
问题 1:消费者如何知道提供者的调用地址呢?

继续我们上述的第一个例子,社区中有人会修理水龙头,那么要想让他帮你来修,你们双方得知道双方的地址,而这个地址,是不是由物业进行保管。因此,我们需要一个 注册中心,来保存服务提供者的地址。消费者要调用服务时,只需从注册中心获取对应服务的提供者地址即可。

架构图如下:

请添加图片描述

主流的注册中心组件:Redis、Zookeeper、Consul、Etcd。Dubbo采用的是ZooKeeper提供服务注册与发现功能。

2、负载均衡
问题 2:如果有多个服务提供者,消费者应该调用哪个服务提供者呢?

我们可以给服务调用方增加负载均衝能力,通过指定不同的算法来决定调用哪一个服务提供者,比如轮询、随机、根据性能动态调用等,在高并发的场景下,需要多个节点或集群来提升整体吞吐能力。。
架构图如下:

请添加图片描述

3、容错机制
问题 3:如果服务调用失败,应该如何处理呢?

为了保证分布式系统的高可用,我们通常会给服务的调用增加一定的容错机制,比如失败重试、降级调用其他接口等等。
架构图如下:

请添加图片描述

4、其他

除了上面几个经典设计外,如果想要做一个优秀的 RPC 框架,还要考虑很多问题。

比如:

  • 服务提供者下线了怎么办?需要一个失效节点剔除机制。
  • 服务消费者每次都从注册中心拉取信息,性能会不会很差?可以使用缓存来优化性能。
  • 如何优化 RPC 框架的传输通讯性能?比如选择合适的网络框架、自定义协议头、节约传输体积等
  • 如何让整个框架更利于扩展?比如使用 Java 的 SPI 机制、配置化等等。

所以,完成 RPC 项目并不难,但做一个完美的 RPC 项目却是难于上青天啊!

总结一下,我们可以通过做一个 RPC 项目学习到网络、序列化、代理、服务注册发现、负载均衡、容错、可扩展设计等知识,相信完成后会收获满满。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1585459.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端代码规范系列,今天聊聊代码注释

开始之前,介绍一下​最近很火的开源技术,低代码。 作为一种软件开发技术逐渐进入了人们的视角里,它利用自身独特的优势占领市场一角——让使用者可以通过可视化的方式,以更少的编码,更快速地构建和交付应用软件&#…

一文带你了解Material, Texture Mapping, Shading, Shader

作者:caven chen 在计算机图形学和三维开发过程中,有几个容易混淆的概念。今天我们来一举拿下。 又可以学习新的知识啦。冲鸭。。。。。。 基础概念 首先我们来介绍一些基础概念: 英文 中文 本质 释义 Material 材质 数据集 表现物体对光的交互…

勒索软件漏洞?在不支付赎金的情况下解密文件

概述 在上一篇文章中,笔者对BianLian勒索软件进行了研究剖析,并且尝试模拟构建了一款针对BianLian勒索软件的解密工具,研究分析过程中,笔者感觉构建勒索软件的解密工具还挺有成就感,因此,笔者准备再找一款…

Elasticsearch8.x 设置密码

文章目录 一、环境说明二、使用elasticsearch-reset-password工具修改1、elasticsearch-reset-password工具位置2、设置密码 一、环境说明 elasticsearch版本:8.13.0 系统版本:Ubuntu 18.04.6 二、使用elasticsearch-reset-password工具修改 1、elast…

Mac环境 llamafile 部署大型语言模型LLM

文章目录 Github官网本地部署 llamafile 是一种可在你自己的电脑上运行的可执行大型语言模型(LLM),它包含了给定的开放 LLM 的权重,以及运行该模型所需的一切。让人惊喜的是,你无需进行任何安装或配置。 Github https…

2023年上半年信息系统项目管理师——综合知识真题与答案解释(1)

2023年上半年信息系统项目管理师 ——综合知识真题与答案解释(1) 零、00时光宝盒 1009 Rejections 1009 拒绝 Once, there was an old man, who was broke, living in a tiny house and owned a beat-up car. 有一次,有一个老人,他破产了&#…

VTK 动画:框架、流程与实现

VTK 动画:框架、流程与实现 VTK 动画:框架、流程与实现vtkAnimationCue 和 vtkAnimationScene 简介vtkAnimationScene 类的重要方法vtkAnimationCue 类的重要方法VTK 动画的基本流程实例:一个简单的 VTK 动画演示程序 VTK是一个非常强大的图形…

报表控件 Stimulsoft 常见问题:从代码启用缓存

Stimulsoft Ultimate (原Stimulsoft Reports.Ultimate)是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能,Stimulsoft Ultimate包含了…

Day 20 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

最大二叉树 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。 通过给定的数组构建最大二叉…

django模板的继承

模板的继承 我们在访问一些访问的网站 这些网站页面整体都差不多 , 只是某一些局部在变化。 模板的继承, 就是自己先选好一个想要继承的模板页面 {% extends home.html %}​ 在继承之后子页面跟模板页面长的是一模一样的, 你需要在模板页面…

Burpsuite+MuMu模拟器12抓包

写在前面 高版本的安卓不能直接安装证书了,比较麻烦。步骤如下。 前置工作 安装adb https://blog.csdn.net/x2584179909/article/details/108319973 安装openssl https://blog.csdn.net/zyhse/article/details/108186278 下载证书 看一下自己的IP burp添加…

Linux Ubantu安装配置教程

Ubuntu是一个基于Linux的开源操作系统,它遵循GNU通用公共许可证,用户可以自由使用、复制、分发和修改。它提供直观易用的桌面环境,适合新手和有经验用户。Ubuntu有强大的软件中心,支持多硬件架构,注重安全和稳定&#…

AcWing 112. 雷达设备 解题思路及代码

先贴个题目: 以及原题链接: 112. 雷达设备 - AcWing题库https://www.acwing.com/problem/content/114/ 这题如果直接枚举点肯定是不行的,但可以把每个小岛的可能雷达设置点抽象成x轴上的线段进行贪心,我们的选点尽量选在线段的重合…

element vue 日期时间组件封装

一、背景 年、月、周、日的时间范围类型&#xff0c;选择对应的日期类型&#xff0c;会传参给后端一个dateType参数&#xff0c;用于后端判断&#xff0c;进行数据抽稀。 二、实现效果 三、代码 完整代码&#xff1a; //年月周日&#xff0c;组件封装 //vue3 setup <scrip…

element-ui中el-radio-group组件绑定点击事件触发多次的解决办法

1、需求 电商首页需求&#xff0c;需要做个单选框&#xff0c;然后点击选中切换图标方向及更换价格升倒序&#xff0c;如下图&#xff1a; 从官网文档看&#xff0c;单选框支持change event&#xff0c;使用click加载按钮处不会触发选中 但是使用 click.native 事件不做处理…

【XR806开发板试用】在 xr806 上移植 LVGL

本文参与极术社区的《基于安谋科技STAR-MC1的XR806开发板试用》活动。 不多废话&#xff0c;直接开搞&#xff0c;先上效果图 准备 开发环境啥的&#xff0c;已经有很多文章了&#xff0c;这里就不再提搭建开发环境的相关内容了。 一个屏幕(1.8’ 128x160) LVGL源码(v8.0.2…

ros 自定义package:在rviz中创建可显示markers的工具包(python)

在rviz中创建可显示markers的工具包 1. 创建using_makers工具包2. rviz部署和测试 1. 创建using_makers工具包 在catkin_ws工作空间下 cd ~/catkin_ws/srccatkin_create_pkg using_markers rospy visualization_msgsmkdir ~/catkin_ws/src/using_markers/scripts/添加basic_s…

D1084 5A低压差电压调整器应用方案,内含电流限制和热保护功能,防止任何过载时产生过高的结温

1、 概述&#xff1a; D1084是一款具有5A输出能力、低压差为1.5V的三端稳压器。输出电压可通过电位器调节或1.5V, 1.8V, 3.3V三个固定电压版。内含电流限制和热保护功能&#xff0c;防止任何过载时产生过高的结温。D1084系列电路有标准TO-220、TO-263和TO-252封装形式。 2、 典…

大话设计模式——21.中介者模式(Mediator Pattern)

简介 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互 UML图 应用场景 大量的连接使得一个对象不可能在没有其他对象的支持下工作&#xff0c;系统表现为一个不可分割的…

redis过期监听机制

转自&#xff1a;https://www.cnblogs.com/wangyunhong/articles/16505079.html 1.redis配置 1.打开conf/redis.conf 文件&#xff0c;取消注释&#xff1a;notify-keyspace-events Ex 2.重启redis 3.如果设置了密码需要重置密码&#xff1a;config set requirepass **** 3…