带你手把手实操一个RPC框架

news2024/11/27 18:48:18

前言:

这篇文章我们来聊一聊RPC框架,为什么要聊RPC呢 ?

首先从个人成长角度,如果一个新时代码农能清楚的了解RPC框架所具备的要素,掌握RPC框架中涉及的服务注册发现、负载均衡、序列化协议、RPC通信协议、Socket通信、异步调用、熔断降级等技术,可以全方位的提升基本素质。

其次,目前市面上也有非常多优秀的框架,GitHub上也有相关源码,但好记性不如烂笔头,只有自己真正了解并且动手去尝试写一个RPC框架,才是我们去掌握这门技术的最优路径。

一、介绍

研究一个概念或者框架,带着三个W去考虑,可能会对他有更加深刻的了解:

1)What,什么是RPC框架,RPC是 Remote Procedure Call 的简称,远程过程调用,那么什么叫远程过程调用呢,你可以理解为我们调用外部(远程)服务就像调用自己本地方法一样。

2)Where,RPC框架用在什么地方,在分布式系统和微服务盛行的今天,各业务系统会被独立拆分出来成为一个个独立的web应用,应用之间的交互和数据传输就成了必不可少的一环,RPC就是为了实现独立服务之间远程交互的框架。

3)Why,为什么需要一个RPC框架,服务之间的调用需要各种场景和因素的考虑,内部原理非常复杂和繁琐,同时在集群情况下,服务的负载均衡,熔断,限流等都是需要去考虑的,这时候就需要一个集服务注册发现、负载均衡、序列化协议、RPC通信协议、Socket通信、异步调用、熔断降级等技术为一体的技术去完成这些公共功能,RPC框架就是在这种情况下应运而生。

目前比较主流的RPC框架包括谷歌开源的GRPC、阿里巴巴的Dubbo、Netflix 的SpringCloud等。

二、RPC框架基本组成

RPC框架需要的最基本的三个要素:

  • ServiceProvider: 服务提供方,提供相关服务接口。
  • ServiceConsumer: 服务消费方,消费服务提供方的接口。
  • Registry: 注册中心,用于进行服务的注册、发现、治理、高可用。

基于三个最基本要素,还会延伸出包括负载均衡器、熔断降级器、通信协议组件、序列化协议等等组件。

一个最简单的RPC调用模型图如下所示:

在这里插入图片描述

下面做一些名词的介绍和解释:

2.1 注册中心

注册中心是RPC框架中的管理者和协调者角色,虽然在远程过程调用中服务消费者会不经过注册中心,会直接向服务提供者发送请求,但是随着我们的服务方越来越多,每个服务的实例也不断变化的,且每个服务的地址,端口等信息是需要通知到消费方的,所以我们需要一个类似“管家”的角色,来负责管理服务注册和发现的工作,这个“管家”我们称之为注册中心。

一个合格的注册中心需要具备包括缓存和持久化服务提供方数据,动态更新服务提供者信息,动态监听服务提供方节点变化,推送节点变化到消费方,查询服务提供方数据等功能。

目前市面上比较流行的注册中心有:Zookper、 Nacos、Consul、Eurake等,针对于上面功能的实现方式也有所不同,以下是注册中心的对比:

ZookeeperNacosConsulEurake
一致性协议CPCP + APCPAP
雪崩保护
多数据中心不支持支持支持支持
自动注销实例支持支持支持支持

2.2 服务提供方(RPC服务端)

其需要对外提供服务接口,一个服务方需要包括启动连接注册中心,注册相关信息到注册中心,提供服务下线和更新机制,维护服务名和服务的映射,序列化和反序列化,启动通信等

目前服务提供方有两种服务提供维度,基于接口的服务提供和基于服务的服务提供,Dubbo3.0 之前是基于接口维度做的服务注册,Dubbo3.0之后渐渐向服务维度的服务注册发现靠拢,SpringCloud是基于服务来进行注册发现的,在云原生和容器化越来越火的今天,基于服务可以更好的适配容器化和云原生。

2.3 服务消费方(RPC消费端)

服务消费方需要具备可以从注册中心拉取服务列表,缓存服务列表,动态监听和更新服务列表的功能,还需要具备针对于服务的负载均衡策略,序列化和反序列化,根据约定的通信协议进行调用等。

目前Dubbo是基于代理和Spring的BeanDefination来实现的,在消费启动的时候会去扫描基于自定义注解或配置的信息,然后生成一个相应的代理对象,注册到Spring容器中,在调用的时候直接通过代理类进行相关一系列调用。SpringCloud是基于HTTP协议和增强版的RestTemplate来实现的,内部实现了Ribbon的负载均衡,消费方可以通过Feign或者RestTemplate实现远程调用。

2.4 通讯框架

通讯框架是服务之间进行IO交互和传输的保证,消费端需要通过通讯框架和提供方进行交互,获取数据,目前市面上主流的基于Java的NIO通讯框架就是Netty。

2.5 通讯协议

通讯协议是消费端和服务端约定好一种交互协议,当消费端拿到服务端提供的IO流之后,需要根据通讯协议获取具体的数据内容,目前TCP通讯协议比较通用的是HTTP、FTP、SMTP协议等,SpringCloud是基于HTTP的通讯协议实现的,Dubbo内部自己集成了一套通讯协议。

业界的主流协议的解决方案可以归纳如下:

  • 消息定长,例如每个报文的大小为固定长度100字节,如果不够用空格补足。
  • 在包尾特殊结束符进行分割。
  • 将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段。

通过对比,我们发现第三点是最为灵活和可拓展的,一般推荐都会使用第三种。

2.6 序列化

2.6.1 概念介绍

序列化(serialization)就是将对象序列化为二进制形式(字节数组),一般也将序列化称为编码(Encode),主要用于网络传输、数据持久化等。

反序列化(deserialization)则是将从网络、磁盘等读取的字节数组还原成原始对象,以便后续业务的进行,一般也将反序列化称为解码(Decode),用于网络传输对象的解码,以便完成远程调用。

2.6.2 序列化协议

  • XML & SOAP

XML是一种常用的序列化和反序列化协议,具有跨机器,跨语言等优点。XML历史悠久,其1.0版本早在1998年就形成标准,并被广泛使用至今,目前金融和银行行业使用较多。

  • JSON

JSON 全称 (Javascript Object Notation) 起源于弱类型语言Javascript, 它的产生来自于一种称之为”Associative array”的概念,其本质是就是采用”Attribute-value”的方式来描述对象。实际上在Javascript和PHP等弱类型语言中,类的描述方式就是Associative array。JSON的具有数据简单,可接受程度高,结构简洁,序列化包体小等特点,目前大部分的公司都是使用这种序列化协议来实现的。

  • Protobuf

由谷歌开发的一款高性能序列化框架,是一个纯粹的展示层协议,可以和各种传输层协议一起使用,目前支持Java、C++、Python 等多种语言,他具有更小的数据量,更快的解析速度,简单的调用等特点,目前得物使用的Dubbo2.7.7版本 默认使用这种序列化协议。

2.7 负载均衡

负载均衡是保证服务提供方在多实例的情况下保证负载的均衡的一种策略,目前大体有如下几种负载均衡策略:

1)轮训,采用计数器的方式,根据计数器的值和实例数量进行取余。

2)随机,采用随机请求的方式,随机一个Random的数值,根据random进行取余。

3)加权轮训,采用权重的方式,给每一个实例配置不同的权重比例,通过比例选择合适的实例。

4) 一致性Hash,采用Hash环的方式,大体的实现思路是通过寻址的方式找到就近的一个节点,具体可以自行网上搜索一下相关文档理解。

三、实现

既然是当作练手实现一个RPC框架,所以会尽量借鉴当前主流的框架,技术选型方面:

注册中心:选择Zookeeper来实现。

服务提供方: 选择基于服务维度来实现服务发现,目前主流框架都是基于这个来做的。

服务消费方: 选择Dubbo类似的基于代理Spring的BeanDefination来实现。

通讯框架: Netty。

通讯协议: 采用上述的第三种方式。

序列化协议: 支持JSON 和 Protobuf。

负载均衡: 实现轮训和随机。

当然,上述的组件都是使用SpringBoot的SPI方式来进行选择的,后续如果需要进行拓展和按不同配置加载,可以通过配置的方式来实现插件的可插拔。

废话不多说,先贴上项目整体结构:

在这里插入图片描述

整体代码结构如上,下面针对模块一一讲解:

3.1 注册中心

代码实现如下:

因为我们是以可拓展和接口方式实现的,所以我们定义了一些接口,通过不同的实现来进行区分,后期可以通过不同的配置来选择合适的注册中心。

在这里插入图片描述

3.2 服务提供方

服务提供方通过使用Spring的事件来进行监听,同时根据声明式的注解来进行解析和注册,同时通过组装元数据,将自己的服务注册到注册中心,完成服务提供方的服务注册,同时启动Netty的客户端,来进行客户端的监听,从而进行服务调用,具体流程图如下:

在这里插入图片描述

部分实现代码如下:

自动装备逻辑:
在这里插入图片描述

使用和服务注册逻辑:
在这里插入图片描述

3.3 服务消费方

服务消费方的逻辑稍微复杂一些,需要通过自动装配来创建新的BeanDefination, 然后从所有的Bean中找到相关的带有RPC注解的参数,重写BeanDefination,重写的Bean需要构建新的元数据和存入客户端缓存,然后通过动态代理的方式,创建一个代理对象,对象使用负载均衡在服务发现的时候选择一个地址,通过Netty的方式进行通信和数据交互,最后返回相关数据对象,具体的流程如下图:
在这里插入图片描述

部分实现代码如下:

启动开始类代码:

在这里插入图片描述
在这里插入图片描述

代理类实现代码:
在这里插入图片描述

负载均衡实现代码:(SPI可拓展模式)

目前采用轮训和随机的方式实现的,后期可根据接口进行拓展。

在这里插入图片描述

3.4 通讯框架

我们使用Netty4实现了通讯框架,采用了NettyClient和NettyServer来实现:
在这里插入图片描述
在这里插入图片描述

3.5 通讯协议

我们目前使用了自定义的通信协议来实现:

第一个字节是魔法数,比如我定义为0X35。

第二个字节代表协议版本号,以便对协议进行扩展,使用不同的协议解析器。

第三个字节是请求类型,如0代表请求1代表响应。

第四个字节表示消息长度,即此四个字节后面此长度的内容是消息content。

在这里插入图片描述

3.6 序列化协议

目前支持JSON和ProtoBuf,后期我们可以通过SPI进行拓展和可配置。

在这里插入图片描述

整体核心调用流程:
在这里插入图片描述

四、总结

本文从整体名词介绍、内部组件组件介绍等两个方面阐述了RPC的框架模型,从技术选型、具体代码等实现了一个RPC框架并应用到项目中。目前RPC框架整体搭建完成,可以正常通过注解接入业务方使用,但还有很多细节需要更仔细地去考虑和思索,比如系统的可拓展性和框架的整体性能等。希望通过阅读本篇文章,可以让读者对RPC有更清晰的了解,让自己的基础技能有一个更高的提升。

*文/Wade

关注得物技术,每周一三五晚18:30更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

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

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

相关文章

Linux 安装 Redis教程

1.切换到目录/use/local/src cd /use/local/src 2.下载文件 wget https://download.redis.io/releases/redis-6.2.6.tar.gz 3.文件解包 tar xzf redis-6.2.6.tar.gz 4.将解压后的包移动到/usr/local/redis目录下 mv redis-6.2.6 /usr/local/redis 5.切换到/usr/local/r…

Vue3这样子结合hook写弹窗组件更快更高效

为什么会有这个想法 在管理后台开发过程中,涉及到太多的弹窗业务弹窗,其中最多的就是“添加XX数据”,“编辑XX数据”,“查看XX详情数据”等弹窗类型最多。 这些弹窗组件的代码,很多都是相同的,例如组件状…

DBCO-PEG-NHS,二苯并环辛炔(DBCO)PEG-NHS衍生物,分子量MV 3.4K 5K

1、产品描述: 二苯并环辛炔(DBCO)PEG-NHS衍生物可以在不需要任何金属催化剂的情况下进行化学反应。菌株促进的环辛炔和叠氮化合物的1,3-偶极环加成反应,也称为无铜点击反应,是一种双正交反应,可使两个分子…

【Java版oj】day05统计回文

目录 一、原题再现 二、问题分析 三、完整代码 一、原题再现 统计回文_牛客题霸_牛客网 描述 “回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。花花非常喜欢这种拥有对称美的回文串,生日的时候她得到两个礼物分别…

ADI Blackfin DSP处理器-BF533的开发详解50:RGBtoGary (图像灰度提取处理)(含源码)

硬件准备 ADSP-EDU-BF533:BF533开发板 AD-HP530ICE:ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 代码实现了图像灰度提取处理,代码运行时,会通过文件系统打开工程文件根目下" …/ImageView"路径中的…

OPENGL ES 2.0 知识串讲(1)――OPENGL ES 2.0 概括

前言 电脑是做什么用的? 电脑又被称为计算机,那么最重要的工作就是计算。看过三体的同学都知道, 电脑中有无数纳米级别的计算单元,通过 0 和 1 的转换,完成加减乘除的操作。 是什么使得电脑工作? 驱动,驱使着硬件完成工作。 谁来写驱动? 制造电脑的公司自己来写驱动,因…

#芯片# N25Q128A21BSF40F

数据手册下载链接:N25Q128A21BSF40F 0. 指令集 1.基本介绍 SPI兼容串行总线接口。108 MHz(最大)时钟频率。推荐工作电压:1.8 V。单电源电压1.7 V至2 V。支持传统SPI协议,Quad I/O或Dual I/O SPI协议。四路/双路I/O指…

bug的生命周期你知道吗?一张图带你看懂它!

目录 1、什么是bug 2、bug的生命周期 3、如何描述一个bug 4、bug的级别 1、什么是bug 软件的bug狭义方面可以理解为是指软件程序的漏洞或缺陷,广义方面除找到程序漏洞之外,还包括测试工程师或用户所发现和提出的软件可改进的细节、或与需求文档存在差…

【全网惟一面向软件测试人员的Python基础教程】- 你知道Python代码是怎样运行的吗?

全网惟一面向软件测试人员的Python基础教程 起点:《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 第三章 你知道Python代码是怎样运行的吗? 文章目录全网惟一面向软件测试人员的Python基础教程…

如何写好科研论文:Introduction(2)

导读 本系列[1]将切片介绍如何写好科研论文,包含了:摘要,背景介绍,方法,结果,讨论等。 由于翻译能力有限,强力推荐有需要的伙伴,直接在文末找到参考链接,阅读原文&#x…

外汇天眼:Swissquote获得CySEC许可证、BUX收购Ninety Nine

新的一周开始了,那么在过去的一周里备受大家关注的外汇行业新闻都有哪些呢?天眼君现在带大家回顾,比如Swissquote获得CySEC许可证、BUX收购西班牙新交易商Ninety Nine的零售经纪部门、Saxo Bank以“时机不合适”为理由终止与SPAC IPO合作。具…

12.3、后渗透测试--持久化后门

攻击主机: Kali 192.168.11.106靶机:windows server 2008 r2192.168.11.134零、为何要创建后门 当成功获取目标系统的访问权限后,需要寻找方法来恢复与目标主机的连接,而无需再进入目标系统。如果目标用户破坏了该连接&#xff0c…

Metal每日分享,虚假颜色混合滤镜效果

本案例的目的是理解如何用Metal实现虚假颜色效果滤镜,使用图像的亮度在两种用户指定的颜色之间进行混合; Demo HarbethDemo地址 实操代码 // 混合颜色 let filter C7FalseColor.init(fristColor: .blue, secondColor: .green)// 方案1: ImageView.im…

BMVC2022 | HR-VQVAE:用于图像重建和生成的基于Hierarchical Residual Learning的VQVAE

原文标题:Hierarchical Residual Learning Based Vector Quantized Variational Autoencoder for Image Reconstruction and Generation 链接:https://bmvc2022.mpi-inf.mpg.de/0636_poster.pdf paper:https://arxiv.org/abs/2208.04554 一…

新业务势头强劲,晨光股份转型之路走得如何?

近期,据网传的一份文件显示,上海晨光文具股份有限公司(以下简称“晨光文具”、“晨光股份”、“晨光”“公司”)将于11月29日起,暂停线上线下店面等渠道的A4纸销售。晨光股份(603899.SH)针对此份…

PreScan快速入门到精通第四十一讲图像分割传感器

图像分割传感器(ISS)是一种生成语义分割图像的工具。它在诸如分类、(深度)学习、行人识别、避免碰撞等应用领域非常有用。ISS通常与相机传感器结合使用,以获得被分割的图像。 摄像机传感器 ISS语义类型颜色 ISS语义目标颜…

Vue3+Vite4+Naive-UI 项目自动导入API和组件

一、Vue3常用API导入 安装依赖 pnpm i -D unplugin-auto-import进行Vite配置 文件名:vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import AutoImport from unplugin-auto-import/vite// https://vitejs.dev/config/ ex…

HDOCK 蛋白蛋白对接软件使用;LZerD网页在线对接

参考: http://hdock.phys.hust.edu.cn/ 注:本文章是取6BOY这蛋白,下载用pymol划分成DDB1-CRBN部分蛋白与BRD4部分蛋白,用这两个蛋白进行软件的对接测试 https://www.rcsb.org/structure/6BOY 一、HDOCK 蛋白蛋白对接软件使用 …

@Enumerated的使用

前言 今天做测试,发现还没有试过实体类中关于枚举项的使用,于是就做了个测试,发现了点问题(发现的问题主要是针对我使用的ORM框架是Ebean,它自带了一个比Enumerated更好用的注解和方式)。 不多说&#xf…

翻硬币(蓝桥杯C/C++B组真题详解)

目录 题目描述:1208. 翻硬币 - AcWing题库 题目思路: 代码详解: 题目描述:1208. 翻硬币 - AcWing题库 题目思路: 这题我们可以用模拟直接模拟操作 也可以直接推出规律 这里就讲解推出的规律 因为每次必须选择两个…