手动实现简易版RPC(上)

手动实现简易版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 项目学习到网络、序列化、代理、服务注册发现、负载均衡、容错、可扩展设计等知识,相信完成后会收获满满。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UI设计解析:入门必读,透彻理解UI的核心概念

UI用户界面是什么? UI是用户界面的缩写。UI是用户与设备、网站或应用程序交互的媒介。目标是使用户体验简单直观。用户只需尽量得到预期的结果。 用户界面是建立在吸引人类感官(视觉、触觉、听觉等)的交互层中的。它不仅包括键盘、鼠标、触…

Linux系统概述与安装

Linux的介绍 Linux内核 Linux内核是 Linux 操作系统主要组件,也是计算机硬件与其软件之间的交互入口。它负责两者之间的通信,还要尽可能高效地管理资源 Linux Shell shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口 Linux文…

kubekey 离线安装harbor、k8s、kubesphere

目录 参考文献 前提条件 部署准备 下载kubukey 离线包配置和制作 配置离线包 制作离线包 离线安装集群 复制KubeKey 和制品 artifact到离线机器 创建初始换、安装配置文件 安装镜像仓库harbor 初始化harbor 项目 修改配置文件 安装k8s集群和kubesphere 手动安装依…

子域名是什么?有什么作用?

在互联网世界中,域名是我们访问网站的关键。每一个公司的网站都需要拥有自己的域名,其中有些大型公司的网站还不止一个域名,除了主域名外还拥有子域名。有些人感到非常困惑,不知道子域名是什么。其实子域名也就是平时所说的二级域…

AI绘本生成解决方案,快速生成高质量的AI绘本视频

美摄科技凭借其深厚的技术积累和前瞻性的市场洞察力,近日推出了一款面向企业的AI绘本生成解决方案,旨在通过智能化、自动化的方式,帮助企业快速将文字内容转化为生动有趣的绘本视频,从而提升内容传播效率,增强品牌影响…

openssl密钥证书管理(Key and Certificate Management)

前言 前两日应别人要求提供一份CSR文件过去,方便他们生成相关证书,对于这一块本来也不熟,于是找到openssl官网,想找找相关的教程看看,一番小找,果有收获,是个宝藏,源文档在这…

AI 对话完善【人工智能】

AI 对话【人工智能】 前言版权开源推荐AI 对话v0版本:基础v1版本:对话数据表tag.jsTagController v2版本:回复中textarea.jsChatController v3版本:流式输出chatLast.jsChatController v4版本:多轮对话QianfanUtilChat…

1、Qt UI控件 -- qucsdk

前言:Qt编写的自定义控件插件的sdk集合,包括了各个操作系统的动态库文件以及控件的头文件和sdk使用demo。类似于Wpf中的LivChart2控件库,都是一些编译好的控件,可以直接集成到项目中。该控件是飞扬青云大神多年前开发的&#xff0…

从零开始:构建、打包并上传个人前端组件库至私有npm仓库的完整指南

文章目录 一、写组件1、注册全局组件方法2、组件13、组件2 二、测试三、发布1、配置package.json2、生成库包3、配置发布信息4、发布 四、使用1、安装2、使用 五、维护1、维护和更新2、注意事项 一、写组件 确定组件库的需求和功能:在开始构建组件库之前&#xff0c…

三相整流桥器件选型计算方法-电压与电流计算公式

三相整流桥的选型主要涉及到两个关键参数:电压和电流。以下是电压与电流的计算公式及选型方法: 电压计算: 输入交流电压有效值(Vrms)是选择整流桥的重要参考。整流桥的额定电压(Vrrm)应至少为输…

echarts tooltip提示框显示不全

一、背景: 写在前面: 自行封装。一个可由多个柱形图叠加而成的图表,命名为someHoverLine(可自定义)。 下面罗列了移动端和web端的封装组件代码; 展示了vue2、uniapp、vue3的不同封装和使用案列。 二、问题描述: 三、解…

数组常用方法

for循环 使用计数器变量来迭代数组元素 var arr [1,2,3,4,5]for(var i0;i<arr.length;i){console.log(array[i]) }上面的i就是计数器变量&#xff0c;初始值为0&#xff0c;每次循环后加1&#xff0c;直到i等于数组长度为止。在循环体内&#xff0c;可以通过数组索引arr[…

C 强制类型转换

强制类型转换是把变量从一种类型转换为另一种数据类型。例如&#xff0c;如果您想存储一个 long 类型的值到一个简单的整型中&#xff0c;您需要把 long 类型强制转换为 int 类型。您可以使用强制类型转换运算符来把值显式地从一种类型转换为另一种类型&#xff0c;如下所示&am…

攻防演练 | redis艰难写shell进入内网

背景 某地市级攻防演练 要求 拿到指定单位的靶标系统&#xff08;必须是web后台管理权限数据库服务器&#xff09; 正式开始 redis未授权 首先通过信息收集获取到了一些IP&#xff0c;且发现一个IP中存在redis未授权。 此时兴冲冲的去尝试写入定时任务反弹shell&#xff…

淘宝评论数据API接口:洞察消费者声音的关键工具

淘宝评论数据API接口&#xff1a;洞察消费者声音的关键工具 请求示例&#xff0c;API接口接入Anzexi58 随着电子商务的蓬勃发展&#xff0c;消费者对于商品的评价和反馈成为了购物决策中不可或缺的一部分。淘宝作为中国最大的电商平台之一&#xff0c;汇聚了海量的商品和评论数…

【SpringBoot】-- mapstruct进行类型转换时Converter实现类不能自动生成代码问题解决

问题描述 我的问题如下&#xff1a; 应该在红色区域生成对应的转换细节&#xff0c;但是这里只返回了一个空对象 问题解决 加入lombok-mapstruct-binding依赖,也要注意依赖引用顺序问题 <dependency><groupId>org.projectlombok</groupId><artifactId&…

photomaker:customizing realistic human photos via stacked id embedding

PhotoMaker: 高效个性化定制人像照片文生图 - 知乎今天分享我们团队最新的工作PhotoMaker的技术细节。该工作开源5天Githubstar数已过6千次&#xff0c;已列入Github官方Trending榜第一位&#xff0c;PaperswithCode热度榜第一位&#xff0c;HuggingFace Spaces趋势榜第一位。项…

小阳同学刷题日记-54. 螺旋矩阵

题目&#xff1a;给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 思路&#xff1a; 初始化四个边界指针&#xff1a;top, bottom, left, right 分别表示当前螺旋遍历的上边界、下边界、左边界和右边界。不断遍历矩阵直…

Windows虚拟主机上多个域名访问同一个网站

近日老板提出了想要多个域名访问同一个网站的想法。这边了解后&#xff0c;由于我们公司使用的是Hostease的Windows虚拟主机产品&#xff0c;因此咨询了Hostease的技术支持&#xff0c;寻求帮助了解到可以实现Windows主机上多个域名访问同一个网站&#xff0c;是需要进入Window…