简易版 RPC 框架实现 1.0 -http实现

RPC 是“远程过程调用(Remote Procedure Call)”的缩写形式,比较通俗的解释是:像本地方法调用一样调用远程的服务。虽然 RPC 的定义非常简单,但是相对完整的、通用的 RPC 框架涉及很多方面的内容,例如注册发现、服务治理、负载均衡、集群容错、RPC 协议等,如下图所示:

在这里插入图片描述
简易 RPC 框架的架构图

本课时我们主要实现RPC 框架的基石部分——远程调用,简易版 RPC 框架一次远程调用的核心流程是这样的:

  1. Client 首先会调用本地的代理,也就是图中的 Proxy。
  2. Client 端 Proxy 会按照协议(Protocol),将调用中传入的数据序列化成字节流。
  3. 之后 Client 会通过网络,将字节数据发送到 Server 端。
  4. Server 端接收到字节数据之后,会按照协议进行反序列化,得到相应的请求信息。
  5. Server 端 Proxy 会根据序列化后的请求信息,调用相应的业务逻辑。
  6. Server 端业务逻辑的返回值,也会按照上述逻辑返回给 Client 端。

这个远程调用的过程,就是我们简易版本 RPC 框架的核心实现,只有理解了这个流程,才能进行后续的开发。

在这里插入图片描述
这个版本写的非常简单实用http协议模拟的rpc实现

  • provider 是服务提供方
  • consumer 是服务调用方
    其实这两个都不算rpc框架内容,是使用者真正的业务代码
  • common 把rpc相关的都放入这一个模块中了

代码比较简单我们就直接从下面两个方便进行分析了

服务提供方

public class Provider {public static void main(String[] args) {Url url = new Url("localhost", 8099);//模拟远程注册中心RemoteMapRegister.regist(HelloService.class.getName(),url);//指明服务的实现类LocalRegister.regist(HelloService.class.getName(), HelloServviceImpl.class);//获取协议Protocal protocol = ProtoaclFactory.getProtocol();//启动 startprotocol.start(url);}
}

URL 统一配置

比较简单不做赘述

远程注册中心

我们这个使用的内存+本地文件存储

public static void regist(String interfaceName, Url url){
//        REGISTER.putIfAbsent(interfaceName, new ArrayList<>());List<Url> urls = REGISTER.get(interfaceName);if(urls == null){List<Url> objects = new ArrayList<>();objects.add(url);REGISTER.put(interfaceName, objects);}else {urls.add(url);}saveFile();}

服务的实现类

实现类方便服务调用方进行调用

public class LocalRegister {private static Map<String, Class> map = new HashMap<>();public static void regist(String interfaceName, Class implClass){map.put(interfaceName,implClass);}public static Class get(String interfaceName){return map.get(interfaceName);}
}

代码中可以看出来非常简单,放到内存map中了

获取协议

其实说白了根据参数获取相关的协议实现

public static Protocal getProtocol(){String name = System.getProperty("protocalName");if(name == null || name.equals("")) name = "http";switch (name){case "http":return new HttpProtoacl();case "dubbo":return new DubboProtocal();default:break;}return new HttpProtoacl();}

根据不同的协议我们开启不同的服务,供服务调用方进行调用

开启服务

//启动 start
protocol.start(url);
根据不同的协议进行开启服务

 @Overridepublic void start(Url url) {HttpServer httpServer = new HttpServer();httpServer.start(url.getHostName(),url.getPort());}

我这用的http服务,底层开启了一个tomcat服务

服务调用方

public static void main(String[] args) {HelloService proxy = ProxyFactory.getProxy(HelloService.class);System.out.println(proxy.say("hellow"));}

服务调用方 生成代理

服务调用方拿不到提供方的实例因此只能通过代理的方式进行访问

 public static <T> T getProxy(final Class interfaceClass){return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Invocation invocation = new Invocation(interfaceClass.getName(), method.getName(), method.getParameterTypes(), args);List<Url> urlList=RemoteMapRegister.get(interfaceClass.getName());Url url = SimpleLoadBalance.random(urlList);Protocal protocol = ProtoaclFactory.getProtocol();String result= protocol.send(url,invocation);return result;}});}

代理中做的事情

  1. 根据远程的注册中心获取URL,即配置信息
  2. 提供方可能存在多个实例, 因此是用负载均衡进行流量负载
  3. 根据协议,发送请求,这个地方我们发送请求没做任何逻辑,实际rpc这个地方会存在很多逻辑
  4. 获取到响应数据返回给调用方

总结

其实这个在一定意义上算不上rpc 框架, 只能说是帮我们简单的理解rpc工作的流程,比只看概念具体一点,方便理解

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

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

相关文章

Redisson 分布式锁原理分析

Redisson 分布式锁原理分析 示例程序 示例程序&#xff1a; public class RedissonTest {public static void main(String[] args) {Config config new Config();config.useSingleServer().setPassword("123456").setAddress("redis://127.0.0.1:6379"…

cool 中的Midway ----node.js的TypeORM的使用

1.介绍 TypeORM | Midway TypeORM 是 node.js 现有社区最成熟的对象关系映射器&#xff08;ORM &#xff09;。本文介绍如何在 Midway 中使用 TypeORM 相关信息&#xff1a; 描述可用于标准项目✅可用于 Serverless✅可用于一体化✅包含独立主框架❌包含独立日志❌ 和老写…

第二十四天-数据可视化Matplotlib

目录 1.介绍 2.使用 1. 安装&#xff1a; 2.创建简单图表 3.图表类型 1.一共分为7类 2.变化 1.折线图 3.分布 ​编辑 1.直方图 2.箱型图 4.关联 1. 散点图&#xff1a; 2.热力图&#xff1a; 5.组成 1.饼图 2.条形图 6.分组 1.簇型散点图 2.分组条形图 3.分…

JOSEF约瑟 TQ-100同期继电器 额定直流电压220V 交流电压100V±10V

TQ-100型同期继电器 TQ-100同期继电器 ​ l 应用 本继电器用于双端供电线路的自动重合闸和备用电源自投装置中&#xff0c;以检查线路电压与母线电压的 相位差和幅值差。 2 主要性能 2 1采用进口集成电路和元器件构成&#xff0c;具有原理先进、性能稳定、可靠性高、动作值精…

Git版本管理--远程仓库

前言&#xff1a; 本文记录学习使用 Git 版本管理工具的学习笔记&#xff0c;通过阅读参考链接中的博文和实际操作&#xff0c;快速的上手使用 Git 工具。 本文参考了引用链接博文里的内容。 引用: 重学Git-Git远程仓库管理_git remote add origin-CSDN博客 Git学习笔记&am…

[自研开源] MyData 数据集成之数据过滤 v0.7.2

开源地址&#xff1a;gitee | github 详细介绍&#xff1a;MyData 基于 Web API 的数据集成平台 部署文档&#xff1a;用 Docker 部署 MyData 使用手册&#xff1a;MyData 使用手册 试用体验&#xff1a;https://demo.mydata.work 交流Q群&#xff1a;430089673 概述 本篇基于…

javaEE——线程的等待和结束

文章目录 Thread 类及常见方法启动一个线程中断一个线程变量型中断调用 interrupt() 方法来通知观察标志位是否被清除 等待一个线程获取当前线程引用休眠当前线程 线程的状态观察线程的所有状态观察 1: 关注 NEW 、 RUNNABLE 、 TERMINATED 状态的切换 多线程带来的风险为什么会…

【大模型系列】问答理解定位(Qwen-VL/Llama2/GPT)

文章目录 1 Qwen-VL(2023, Alibaba)1.1 网络结构1.2 模型训练 2 Llama2(2023, Meta)2.1 网络结构2.1.1 MHA/GQA/MQA2.1.2 RoPE(Rotary Position Embedding, 旋转式位置编码)2.1.3 RMSNorm 2.2 推理2.2.1 集束搜索(beam search)2.2.2 RoPE外推 3 GPT系列(OpenAI) 1 Qwen-VL(2023…

android中单例模式为什么会引起内存泄漏?

单例模式使用不恰当会造成内存泄漏。因为单例的静态特性使得单例的生命周期和应用的生命周期一样长&#xff0c; 如果一个对象已经不需要使用了&#xff0c;但是单例对象还持有该对象的引用&#xff0c;那么这个对象就不能被正常回收&#xff0c;因此会导致内存泄漏。 举个例子…

【数据可视化】使用Python + Gephi,构建中医方剂关系网络图!

代码和示例数据下载 前言 在这篇文章中&#xff0c;我们将会可视化 《七版方剂学》 的药材的关系&#xff0c;我们将使用Python制作节点和边的数据&#xff0c;然后在Gephi中绘制出方剂的网络图。 Gephi是一个专门用于构建网络图的工具&#xff0c;只要你能提供节点和边的数…

机器学习算法在数据挖掘中的应用

在数据挖掘的实践中&#xff0c;各种机器学习算法都扮演着重要的角色&#xff0c;它们能够从数据中学习规律和模式&#xff0c;并用于预测、分类、聚类等任务。以下是几种常见的机器学习算法以及它们在数据挖掘任务中的应用场景和优缺点。 1. 决策树&#xff08;Decision Tree…

Golang的CSP模型讲解

一.CSP是什么 CSP 是 Communicating Sequential Process 的简称&#xff0c;中文可以叫做通信顺序进程&#xff0c;是一种并发编程模型&#xff0c;是一个很强大的并发数据模型&#xff0c;是上个世纪七十年代提出的&#xff0c;用于描述两个独立的并发实体通过共享的通讯chann…

Stable Diffusion科普文章【附升级gpt4.0秘笈】

随着人工智能技术的飞速发展&#xff0c;我们越来越多地看到计算机生成的艺术作品出现在我们的生活中。其中&#xff0c;Stable Diffusion作为一种创新的图像生成技术&#xff0c;正在引领一场艺术创作的革命。本文将为您科普Stable Diffusion的相关知识&#xff0c;带您走进这…

微信小程序睡眠X秒【while循环模式】

// 微信小程序睡眠X秒sleep(numberMillis) { var now new Date(); var exitTime now.getTime() numberMillis; while (true) { now new Date(); if (now.getTime() > exitTime) {return;}} }, // 微信小程序睡眠X秒 this.sleep(2000); 参考&#xff1a;微信小程序睡眠…

Linux/Ubuntu/Debian控制台启动的程序和terminal分离的方法-正在运行怎么关闭窗口

disown 是一个 shell 内置函数&#xff0c;它从 shell 的作业表中删除指定的作业&#xff0c;使它们免受挂起的影响。 使用方法如下&#xff1a; 首先&#xff0c;正常运行命令&#xff1a; 你的命令然后&#xff0c;按 Ctrl Z 暂停命令。 现在&#xff0c;运行&#xff…

MT1069 圆切平面

n个圆最多把平面分成几部分&#xff1f;输入圆的数量N&#xff0c;问最多把平面分成几块。比如一个圆以把一个平面切割成2块。 不考虑负数&#xff0c;0或者其他特殊情况。 格式 输入格式&#xff1a;输入为整型 输出格式&#xff1a;输出为整型 样例 1 输入&#xff1a; …

全量知识系统“全基因序列” 的百度AI答问 之1

在您所描述的框架下&#xff0c;我们可以开始探索“知识”实体的起点以及如何认识它。首先&#xff0c;让我们明确一下“实体”的定义和性质。实体&#xff0c;在哲学和许多其他学科中&#xff0c;通常被理解为存在于我们世界中的具体事物或抽象概念。它们可以是物理的&#xf…

Flink 集群部署模式

文章目录 前言一、会话模式&#xff08;Session Mode&#xff09;二、单作业模式&#xff08;Per-Job Mode&#xff09;三、应用模式&#xff08;Application Mode&#xff09; 前言 Flink支持多种集群部署模式&#xff0c;以满足不同场景和需求。以下是Flink的主要集群部署模…

springboot多模块下swaggar界面出现异常(Knife4j文档请求异常)或者界面不报错但是没有显示任何信息

继上一篇博文&#xff0c;我们解决了多模块下扫描不到子模块的原因,建议先看上一个博客了解项目结构&#xff1a; springboot 多模块启动报错Field XXX required a bean of type XXX that could not be found. 接下来我们来解决swaggar异常的原因&#xff0c;我们成功启动项目…

QML 布局管理器之ColumnLayout

一.ColumnLayout讲解 QML中的ColumnLayout是一种布局元素&#xff0c;用于在垂直列中排列其子元素。它的主要使用下列附加属性: Layout.minimumWidth Layout.minimumHeight Layout.preferredWidth Layout.preferredHeight Layout.maximumWidth Layout.maximumHeight Layout.fil…