【BlossomRPC】手把手教你写一个RPC协议

文章目录

  • 新的开始
  • 什么是RPC?
  • 设计一个RPC需要些什么?

新的开始

经常会遇到一些项目,看着看着就发现看不懂文档了,也就是会出现一些跳过讲解的文章,使得自己很难了解某种中间件的开发全貌,所以想着自己先设计一个比较简易的RPC框架,在实现所有功能的前提下,向公司内部的技术分享一样,用口语化的方式讲述RPC框架,使得大家更容易理解。
这也是BlossomRPC项目的初衷。

RPC项目

配置中心项目

网关项目
再之前的网关项目中,我们已经了解到了Netty再网络通信中的作用,我们可以使用Netty开发非常多的东西,比如实现WebSocket,Http的服务器,上位机等。
只要是涉及到网络通信这一块的东西,都可以考虑使用我们的Netty去进行设计。
这一章节,我们将使用Netty去实现一个简单的RPC框架。
好的,接下来我们继续按照自顶向下的方式来学习这个自研的RPC框架。
(嘿嘿,最近在读金字塔原理,这不得让我试试我的学习成果)
因此,为了能够向你讲解清楚并且让你最后能理解这个项目,我会按照如下的方式为你介绍在这一章里面你会知道并且学习到什么东西。

  1. 什么是RPC
  2. 如何自己实现一个RPC框架
  3. 代码实战
    ok,let‘s go !

什么是RPC?

我在字节的时候,我和我的mentor闲聊聊到了RPC和HTTP。
然后就这个问题他问了我很多东西。
因此,再聊RPC之前,我们得先知道什么是RPC?他和HTTP的区别是什么?为什么我们会经常将PRC和HTTP去做比较呢?以及为什么企业内网中通信更多用的是RPC,而公网通信更多用的是HTTP?
我们随便搜索一下都能看到如下的对RPC的介绍:
RPC(Remote Procedure Call)是一种网络通信协议,它允许程序调用在另一台机器上的程序或服务,就像调用本地对象一样。RPC抽象了网络通信的复杂性,使得开发者可以像调用本地函数一样调用远程函数。RPC框架通常处理网络通信、数据的序列化/反序列化和错误处理等。
但是其实光看上面的描述其实还是没办法让我们对RPC有一个详细的了解,他依旧很抽象。
根据金字塔原理,我们知道这句话的目的是为了概述RPC的功能和作用,那么这段话中的每一个小句子的都是为了概述RPC来服务的。所以我们可以试图对上面的话中抽取一些关键词。

  1. 网络通信协议:RPC是一种用于网络间通信的方案。
  2. 程序调用:RPC允许一个程序调用另一台机器上的程序或服务。
  3. 类似本地对象调用:RPC使远程服务调用在使用上类似于调用本地对象。
  4. 抽象网络复杂性:RPC抽象化了底层的网络通信细节,简化了远程调用的过程。
  5. 调用远程函数:RPC的主要功能是允许开发者执行远程服务器上的函数或方法。
  6. 处理序列化/反序列化:RPC框架通常负责数据的序列化(将对象转换为网络传输的格式)和反序列化(将接收的数据转换回对象)。
  7. 错误处理:RPC框架通常包含错误处理机制,以处理网络通信中可能发生的问题。
    因此,其实我们可以对上面的话举个例子,然后进行一个总结描述:
    用白话来说,RPC(远程过程调用)就像是一个允许你通过电话指挥别人帮你完成任务的方法,而这个“别人”就是一台位于远处的电脑。想象一下,你需要完成一个任务,但是需要的工具或信息在别的地方,你就可以通过RPC来“打电话”给那台远程电脑,让它帮你完成这个任务。这个过程对你来说就像是让自己电脑上的一个程序做事一样简单,你不需要知道远程电脑是如何完成任务的,也不需要自己处理复杂的网络通信细节,你只需要负责拨号就行了,也就是说,你只需要知道对方的号码,然后接通电话的那一刻,说出你要对方做的使其即可。
    简而言之,RPC让远程电脑上的程序就像是你自己电脑上的程序一样容易调用。
    专业一点的说:RPC是一种能帮助你轻易调用远程机器上的程序接口并且帮助你屏蔽了各种底层复杂处理的方案,使得我们能专注于业务代码的开发而不是考虑底层细节。
    因此,为了能实现上面的目的,RPC一定需要完成上面的几个点,并且暴露出一个易于你调用的接口,使得你能非常方便的完成“打电话”这个动作。

那么第一个问题就回答完毕了,第二个问题我们经常能在网络上看见对它的讨论。
RPC和HTTP经常被拿来比较,主要是因为它们都被广泛用于服务间的通信,但在实现细节、性能、适用场景上有显著的不同。了解这些差异对于选择合适的通信机制来满足特定应用的需求非常重要。
这里我就直接引用知乎大佬的原话了:

既然有 HTTP 请求,为什么还要用 RPC 调用?
所以通过文章我们了解到,一个是技术方案,一个是通信协议。
而RPC这个技术方案,就包含了对通信协议的使用,因此,你可以直接使用HTTP协议作为RPC底层的传输机制,但是,你也可以使用更高效的协议,TCP/UDP都可以。

聊完了区别,我们来回答最后一个问题,其实这个问题就是在问,他和HTTP的优缺点了。
● HTTP:可读性好,跨语言,易于通过防火墙。优于RPC的地方在于其通用性和易用性,尤其是在构建面向公众的Web API时。
● RPC:更专注于效率和性能,适合用于内部服务之间的通信。RPC通常更快,因为它可以使用比HTTP更高效的传输协议和序列化方法。
● HTTP:由于工作在应用层,它包含了较多的协议头信息,因此相对于RPC在数据传输效率上可能较低。
● RPC:可能不如HTTP那样直观易用,且在跨语言支持和标准化方面可能不如HTTP强。
所以,我们总结一下,就能知道最后一问的答案(这一问就是我mentor问我的,她说我的当初的答案差点意思,嘿嘿,现在补充一下):

  1. 性能和效率:企业内网中的服务通常追求高效率和低延迟,RPC支持的高效二进制序列化和简化的通信协议在这方面表现更好。
  2. 安全和隔离:内网环境相对封闭和安全,服务间可以使用更为复杂的通信机制(如RPC),而无需担心公网中的安全问题。
  3. 协议和标准:HTTP作为互联网的基础协议,更适合用于构建公共API和服务。它的标准化和广泛支持使得不同环境和平台之间的通信更加容易。
  4. 兼容性和可访问性:HTTP在公网上的普遍兼容性使其成为互联网服务的理想选择,特别是在需要与浏览器等客户端交互时。

好的,我们基本了解完毕什么是RPC之后,我们就可以开始分析设计一个RPC框架需要用到那些知识了。

设计一个RPC需要些什么?

在着手编码之前,我们得先分析清楚设计一个RPC框架需要在那些方面下功夫去设计。
由于这个项目不会涉及的特别复杂,只是为了简单演示一下自己开发一个RPC框架所需要设计到的知识,所以我们一切从简。
我们也按照这张图片的方式进行处理,最终也可以完成对RPC请求的处理。
在这里插入图片描述
可以发现,对于一个RPC项目,我们需要从如下几个方面来考虑:

  1. 接口定义与服务规范
  2. 客户端代理(对客户端的请求进行代理)
  3. 序列化与反序列化
  4. 网络通信
  5. 服务注册与发现

了解到这些之后,我们就可以开始粗略的分析一下每一个点,然后详细的分析每一个点下面可能遇到的问题以及需要考虑到的一些东西。
如下是我列的一个粗略的大纲:

分析一下需要做的事情
1:消息协议的定义
- 版本 协议版本 1byte
- 压缩/序列化等算法的使用 1byte
- 消息类型 1byte
- 请求ID 8byte
- 消息长度 4byte
- 消息内容 Object

2:编写编码器和解码器
- Server和Client都需要引入编解码器
- 编解码器需要对我这个特定的协议进行解析(基于上面的协议)
- 编解码器只是解析数据,最终数据的处理应该用Handler去操作

3:处理序列化和反序列化
- 参考grpc、google、
- 可以考虑自己实现,也可以考虑使用开源的框架
- Java原生序列化 、 Json 、Arvo 、 protobuf

4:编写Handler处理器

------------完成协议部分-------------
------------客户端代理部分-----------

5: 对客户端带有注解的服务进行代理
- JDK动态代理、CGLIB、SpringAop
- 其中Spring这种方式可以考虑使用BeanFactory的方式来得到代理对象
- 思考用什么样的一种方式可以对使用了我提供的注解的类进行代理的创建
-- BeanRegistry/BeanFactory/Bean反射

6:编写注册中心代码/服务感知
- 项目是要整合springboot进行使用的
-- 要确保项目于springboot的无缝整合 减少用户感知
- 如何整合注册中心比如zk、nacos
- 如何编写一种通用的模板使得用户无感知,而只需要用到注解
-- 考虑使用AutoConfiguration+Conditional类型的注解进行依赖引入的判断
-- 如果引入了Nacos相关的重点依赖,那么注册中心用nacos
-- 也可以考虑提供枚举类型 / 通过配置文件的方式 让用户手动的去选择选用的注册中心
-- 优化用户体验,考虑在spring的application类型的文件中添加配置文件注释
-- 比如考虑到Spring中提供的各种Aware/Processor的使用
--- 比如ApplicatiopnAware/BeanFactoryAware/BeanClassLoaderAware/EnvironmentAware
--- 策略模式/单例模式/模板方法注册
--- 负载均衡的考虑
--- 考虑服务注册的时候注册上去的元数据信息
--- 如何从多个实例中选取一个特定实例(负载均衡算法实现)

分析意义
1: 某些公司那边并不使用rpc通信的方式,他们用的是mq通信
2: 基站即服务
3: 什么时候用http,什么使用用rpc?
--------------------------

那么接下来,我们就按照上面的大纲来分析一下设计我们自己的RPC需要用到那些技术。
首先是序列化和反序列化,这里可以考虑两种方法,一种是使用最简单的Java原生的对象处理流,也就是Java自带的序列化,当然,这种方法并不好,性能低的同时,安全性以及移植性都很差。
第二种方法就是使用JSON,这是非常常见且简单的序列化方案。
其次就是使用Arvo、Protobuf这些序列化框架。
在这个项目中,序列化并不是非常重要的重头戏,因此我就直接选用JSON和原生Java序列化了。
当然,你甚至可以自定义序列化算法。
网络通信上,我们可以选择使用HTTP进行数据的传输,也可以使用Netty,这里很明显,我们选择Netty。
其次就是框架了,我们选择使用2.7.8版本的SpringBoot,这个版本已经支持了非常多的特性,并且可以非常快速简单的实现自动注入。
最后,注册中心我们选用Nacos和Zookeeper。
当然,我们的项目也支持你使用自己实现的注册中心。
(嘿嘿,自研注册中心正在开发中,敬请期待)
所以,了解完毕了上面,我们列出如下的技术栈:
SpringBoot2.7.8
Netty4.1.52
fastjson
好的,那么接下来我们正式开始准备开发。

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

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

相关文章

编程实现黄金分割法、平分法和不精确一维搜索等最优化算法

解: 1、黄金分割法 思想: 黄金分割法是通过不断缩短搜索区间的长度来寻求一维函数的极小点,这种方法的基本原理是:在搜索区间[a,b]内按如下规则对称地取两点a1和a2 a1a0.382(b-a); a2a0.618(b-a); 黄金分割法的搜索过程是&#x…

代码随想录算法训练营第二十五天| 回溯算法理论基础、LeetCode77.组合

一、216.组合总和III 题目链接/文章讲解/视频讲解: https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html 状态:已解决 1.思路 做过77题(上篇博客)后,这道题也就不难了,无非是多…

数字化转型导师坚鹏:BLM新质生产力发展方法论

BLM新质生产力发展方法论 ——新质生产力发展之知行果合一 课程背景: 很多学员存在以下问题: 不知道如何理解新质生产力? 不清楚如何发展新质生产力? 不知道新质生产力发展案例? 课程特色: 原创…

echarts统计图占满整个容器

原先的统计图表没有占满容器,感觉整个被压缩了 网上查阅相关资料后发现需要设置grid一个配置项(有些数值需要根据实际情况进行调整) grid:{top:"0px",left:"0px",right:"0px",bottom:"0px"} 对于gr…

用户登录.java

分析: 1,用String来定义两个变量,记录正确的用户名和密码----->直接赋值得来 2,键盘录入用户名和密码------>new开辟空间得来,存的是地址值 他们直接用比较大小,必定不相同,需要用到String里面的方…

沙箱安全机制

Java安全模型的核心就是Java沙箱(sandbox), 什么是沙箱? 沙箱是一个 限制程序运行的环境。沙箱机制就是将Java代码限定在虚拟机(JVM) 特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证 对代码的 有效隔…

QT中的文件操作QFile、QDataStream、QTextStream、QBuffer

文件操作概述 1、Qt中IO操作的处理方式 (1)、Qt通过统一的接口简化了文件与外部设备的操作方式 (2)、Qt中的文件被看做是一种特殊的外部设备 (3)、Qt中的文件操作与外部设备操作相同 2、IO操作中的关键…

基于协同过滤算法的图书推荐系统(ssm+jsp)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的基于协同过滤算法的图书推荐系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 管理员功能需求…

C语言例1-11:语句 while(!a); 中的表达式 !a 可以替换为

A. a!1 B. a!0 C. a0 D. a1 答案&#xff1a;C while()成真才执行&#xff0c;所以!a1 &#xff0c;也就是 a0 原代码如下&#xff1a; #include<stdio.h> int main(void) {int a0;while(!a){a;printf("a\n");} return 0; } 结果如…

Soot入门学习笔记

Soot 适合参考的文档和教程如下&#xff1a; 北京大学软件分析技术 南京大学软件分析 Tutorials for soot McGill University 198:515 (vt.edu) 比较好的笔记资料&#xff1a; 南京大学《软件分析》课程笔记 比较好的入门作业或者案例&#xff1a; CSCE710 Assignmen…

vue3如何二次封装el-upload组件进行图片上传及删除

实现功能&#xff1a; 1、封装el-upload组件&#xff0c;父组件可以控制图片上传框的宽高 2、父组件可以传入提示信息&#xff0c;利用具名插槽 3、上传前的校验 4、实现删除功能 不同配置下的效果&#xff1a; 下边案例是图片上传的时候没有掉接口&#xff0c;在整体提交的时…

省级-能源结构数据(电力消费水平)(2000-2022年)

能源结构指能源总生产量或总消费量中各类一次能源、二次能源的构成及其比例关系。它是能源系统工程研究的重要内容&#xff0c;直接影响着国民经济各部门的最终用能方式&#xff0c;并反映了人民的生活水平。能源结构主要由生产结构和消费结构组成。 本数据通过电力消费水平来…

HarmonyOS 应用开发之FA模型与Stage模型应用组件

应用配置文件概述&#xff08;FA模型&#xff09; 每个应用项目必须在项目的代码目录下加入配置文件&#xff0c;这些配置文件会向编译工具、操作系统和应用市场提供描述应用的基本信息。 应用配置文件需申明以下内容&#xff1a; 应用的软件Bundle名称&#xff0c;应用的开发…

Delphi 12 安卓 部署文件,不支持中文文件名

procedure TForm3.Button1Click(Sender: TObject); var sFileName:string; begin sFileName:TPath.Combine(TPath.GetDocumentsPath,禁止吸烟.wav); showmessage(sFileName); MediaPlayer1.Stop ; MediaPlayer1.FileName: sFileName; MediaPlayer1.Play; end;

Python之Opencv教程(3):人脸识别

1、人脸识别代码 直接上代码&#xff1a; import cv2# 加载训练数据集文件 recogizer cv2.face.LBPHFaceRecognizer_create()recogizer.read(trainer/trainer.yml)# 准备识别的图片 img cv2.imread(images/lisa.jpg) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)face_dete…

Linux文件系统权限

文件的一般权限 每个文件针对每类访问者定义了三种主要权限&#xff1a; r&#xff1a;read 读 w&#xff1a;write 写 x&#xff1a;execute 执行 所属者/组/其他用户权限的字符表示二进制表示八进制表示---0000--x0011-w-0102-wx0113r--1004r-x1015rw-1106rwx1117 文件/目…

企业培训系统功能介绍

在当今知识经济时代&#xff0c;企业的竞争力在很大程度上取决于员工的专业能力和综合素质。为了适应不断变化的市场需求和技术进步&#xff0c;企业需要对员工进行持续有效的培训。一个高效的企业培训系统对企业人才培训至关重要。以下介绍一下企业培训系统的主要功能&#xf…

《操作系统导论》第15章读书笔记:机制:地址转换(address translation)

《操作系统导论》第15章读书笔记&#xff1a;机制&#xff1a;地址转换&#xff08;address translation&#xff09; —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第15章读书笔记&#xff1a;机制&#xff1a;地址转换&#xff08;address translation&#xff09;1.前…

c语言:用do-while输出前40项的斐波那契数值

求Fibonacci数列的前40个元素。该数列的特点是第1、2两个数为1、1。从第3个数开始&#xff0c;每数是其前两个数之和。 分析&#xff1a;从题意可以用如下等式来表示斐波那契数列&#xff1a; 1&#xff0c; 1&#xff0c; 2&#xff0c; 3&#xff0c; 5&#xff0c; 8&#x…

FA模型切换Stage模型组件切换之PageAbility切换

FA模型中PageAbility对应Stage模型中的UIAbility&#xff0c;PageAbility切换为UIAbility的方法如下。 在Stage应用中 创建UIAbility。 将FA应用中PageAbility的代码迁移到新创建的UIAbility中。 FA应用中PageAbility和Stage应用中的UIAbility生命周期基本一致&#xff0c;两者…