RPC通信原理(一)

news2024/11/19 4:17:10

RPC通信原理

RPC的概念

如果现在我有一个电商项目,用户要查询订单,自然而然是通过Service接口来调用订单的实现类。

我们把用户模块和订单模块都放在一起,打包成一个war包,然后再tomcat上运行,tomcat占有一个进程,这个项目也是在这个进程中运行的,模块之间的调用也是在进程的本地进行调用,那么如果我是一个分布式项目该怎么解决呢?

现在用户和订单模块部署在两台服务器上,这时候用户模块就不能直接调用订单模块了,只能够通过网络来进行调用,而RPC就是用来干这个事情的,通过RPC来进行服务之间的远程调用

特点:

  • 把远程实现搬到了本地,效果上远程调用和本地调用没区别
  • 这里的搬运到了本地不是真的把代码CV到调用者本地,而是RPC的一种无侵入式的抽象,调用者可以调用本地服务一样去调用远程的服务,其中的网络协议,数据传输等实现细节被RPC屏蔽掉。
  • 使用CS模式,客户端发起请求并传递参数,服务端接收参数后执行,并将执行结果返回
  • 底层网络通信细节对上层开发者屏蔽,上层开发者无需为这一交互过程做额外的编码,做到应用无侵入

RPC的应用场景有哪些?

需要远程通信的各类场景

小结

RPC中的关键技术点

调用过程如下:

调用流程总结:

首先客户端要远程调用这个接口,这个接口会由RPC底层动态代理实现远程调用,然后通过序列化数据,以及使用互相通信的协议编码,通过网络传输到对端服务器上,服务器从网络模块拿到数据,经过解码、反序列化一系列操作之后,调用这个函数的实现方法,把结果再次经过序列化和协议编码处理之后发送给客户端,客户端进行协议解码和反序列化得到数据。

小结

RPC中的高级特性

动态感知并且自动切换

当服务器压力小的时候可以减少RPC集群数量,当服务器压力大的时候可以增加RPC集群节点,这一过程都是自动完成的,这一功能依赖于注册中心

服务发现模块会监听注册中心,看注册中心时候发送消息给服务发现模块,当注册中心的配置发生变化之后,注册中心会像服务发现模块发送消息,告知它配置已经发生了修改,然后去重写拉取配置,写入本地缓存当中。

小结

RPC的优势

Zookeeper的注册原理及存储结构

Zookeeper是一个树形结构,通过路径+节点来标识一个节点。

https://www.runoob.com/w3cnote/zookeeper-tutorial.html

注册中心Dubbo会记录有哪些远程调用的接口,及其生产者和消费者,对于远程调用的接口是一个持久节点,会一直存在,而生产者和消费者却是临时节点,这是因为:

  • 容错与自动摘除

    • 当提供服务的生产者因为故障或正常关闭时,Zookeeper上的临时节点会自动删除。这样消费者(Consumer)从Zookeeper获取的服务列表中将不再包含已下线的服务提供者,实现了服务列表的自动更新和失效剔除。
  • 服务实例生命周期管理

    • 临时节点的存在与Zookeeper客户端会话绑定,当服务提供者的Zookeeper客户端会话中断(例如进程退出、网络断开等情况)时,对应的临时节点就会被清理,这与服务提供者的生命周期保持一致。
  • 负载均衡与集群伸缩性

    • 使用临时节点可以方便地支持集群环境下的动态扩容与缩容,新的服务提供者上线或者旧的提供者下线,都能迅速反映到服务注册中心,进而使得消费者能及时感知并调整访问策略。

Dubbo协议异步单一长连接原理与优势

2. 异步单一长连接原理

2.1 异步通信

Dubbo协议采用异步通信模型,即客户端发送请求后不需要等待服务端响应,可以立即进行其他操作。这种模型的核心在于使用了NIO(Non-blocking I/O)技术,通过事件驱动和回调机制来实现请求的并发处理。

具体来说,客户端在发送请求后,将请求信息注册到事件多路复用器上。当服务端响应到达时,事件多路复用器会触发相应的回调函数进行处理。这样一来,客户端就可以异步地处理多个请求,提高了系统的并发能力和吞吐量。

2.2 单一长连接

Dubbo协议使用单一长连接的方式来进行通信。所谓单一长连接,就是指客户端与服务端之间只建立一个TCP连接,并保持长时间的有效性。

这种设计方案有以下几个优势:

2.2.1 连接复用

由于只有一个TCP连接,不需要频繁地建立和关闭连接,避免了TCP连接的三次握手和四次挥手的开销。同时,连接的复用还可以减轻网络设备的负担,提高网络的利用率。

2.2.2 减少资源消耗

每个TCP连接都会占用一定的系统内存和CPU资源,如果每个请求都需要建立新的连接,那么系统资源开销将会非常大。而采用单一长连接的方式,可以大幅度降低资源的消耗,提高系统的稳定性和可伸缩性。

2.2.3 保证顺序性

由于Dubbo协议仅使用一个连接,发送的请求和接收的响应不会交错。这意味着请求和响应可以按照发送的顺序进行处理,不会出现乱序的情况。这在一些有序性要求较高的场景中非常重要。

3. 异步单一长连接的优势

异步单一长连接作为Dubbo协议的核心设计,具有以下几个显著的优势:

3.1 减少网络开销

采用异步通信模型和单一长连接方式可以减少网络的开销,避免了频繁地建立和关闭连接带来的额外开销。这对于海量请求的场景尤为重要,可以提升系统的性能和吞吐量。

3.2 提高系统的稳定性和可伸缩性

由于单一长连接减少了资源消耗,系统的稳定性和可伸缩性得到了提高。在高并发情况下,系统能够更好地承受请求的压力,同时也降低了系统崩溃的风险。

3.3 简化系统维护和监控

采用单一长连接的方式简化了系统的维护和监控工作。只需要关注一个TCP连接的状态和性能指标,而不需要管理多个独立的连接。这有助于提高运维效率和降低维护成本。

3.4 保证请求顺序性

由于异步通信模型和单一长连接的特性,Dubbo协议能够保证请求和响应的顺序性。这对于某些有序性要求的业务场景非常重要,例如金融交易系统中的订单处理。

长链接中断的情况:

  1. 服务端或客户端主动断开连接。
  2. 网络故障导致连接中断。
  3. 客户端(如消费方应用)或者服务端进程终止。

代理技术

JDK Proxy原理

//JDK的动态代理
public class JdkProxyTest {
    public static void main(String[] args) {
     //会将生成的class保存在工程根目录下的 com/sun/proxy 目录里面
    System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        BookService bookService=(BookService) Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(), //类加载器
                new Class[]{BookService.class}, //要动态代理实现的方法
                new Handler() //要调用的方法实现
        );
        Book book=bookService.findById("100");
        System.out.println(book);
    }

    static class Handler implements InvocationHandler{

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //发起远程网络调用
            System.out.println("模拟发起网络远程调用");
            Book book=new Book();
            book.setId(args[0].toString());
            book.setName("斗破苍穹");
            book.setTitle("玄幻");
            book.setTag("玄幻");
            book.setContent("爽文");
            return book;
        }
    }
}

查看其代理类:

public final class $Proxy0 extends Proxy implements BookService {
    private static Method m1;
    private static Method m2;
    private static Method m0;
    private static Method m3;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final Book findById(String var1) throws  {
        try {
            return (Book)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("BookService").getMethod("findById", Class.forName("java.lang.String"));
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

对上述代码精简一下:

public final class $Proxy0 extends Proxy implements BookService {
    private static Method m1;
    private static Method m2;
    private static Method m0;
    private static Method m3; //findById方法

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final Book findById(String var1) throws  {
        try {
            return (Book)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("BookService").getMethod("findById", Class.forName("java.lang.String"));
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
super(var1);//查看一下这个函数,如下

	protected InvocationHandler h;

    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }
    public final Book findById(String var1) throws  {
        try {
            return (Book)super.h.invoke(this, m3, new Object[]{var1}); //这里的h就是我们传递过来的Handler方法,也就是直接调用我们自己实现的handler方法
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

其他动态代理的解决方案

小结

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

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

相关文章

vue模板语法介绍及内置指令用法

1、文本差值(大括号、v-text、v-htm指令) 最基本的数据绑定就是文本差值,格式为“Mustache”语法(双大括号); 双大括号只能解析文本不能解析html,如需解析html则需使用v-html指令;…

【四 (2)数据可视化之 Matplotlib 常用图表及代码实现 】

目录 文章导航一、介绍二、安装Matplotlib三、导入Matplotlib四、设置可以中文显示四、常用图形1、散点图(Scatter Plot)2.1、线性图(Line Plot)2.2、堆叠折线图2.3、多图例折线图3.1、柱状图/条形图(Bar Chart&#x…

AI基础知识问答(1)

1.什么是线性判别分析法(FDA)? 线性判别分析是一种对于监督数据降维的经典方法。通过对数据标准化,求得类内散度矩阵和类间散度矩阵,寻找一个投影矩阵W,使得同类样例的投影点尽可能接近,异类样…

使用采购管理软件构建更高效的采购模式

采购流程是企业整个采购部门的关键要素。无论企业规模大小,构建采购流程的模式都将直接影响企业控制成本、管理风险和保持流程弹性的能力。 下面我们将解释采购模式的类型、优缺点,以及如何确定哪种模式最适合你的采购部门。 集中采购的优缺点 在集中采…

HTML小游戏26 —— HTML5密室逃生游戏(附完整源码)

💂 网站推荐:【神级源码资源网】【摸鱼小游戏】 【工具大全】🤟 基于Web端打造的:👉【轻量化工具创作平台】💅 想寻找共同学习交流、摸鱼划水的小伙伴,请点击【学习交流群】 本节教程我会带大家使用 HTML 、…

编程入行指南:从代码小白到技术大牛的“码农”奇幻漂流

码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! 在这个飞速发展的信息时代,技术不断推陈出新,程序员若想保持行业翘楚地位,必须持续汲取新知、…

SQLiteC/C++接口详细介绍之sqlite3类(十六)

返回目录:SQLite—免费开源数据库系列文章目录 上一篇:SQLiteC/C接口详细介绍之sqlite3类(十五) 下一篇: SQLiteC/C接口详细介绍之sqlite3类(十七)(未发表) 50.sqlite…

相机sd卡照片删除后数据恢复,相机sd卡中的照片被删除后如何恢复数据

当我们使用相机拍摄照片时,有时会不小心删除了一些重要的照片。这可能是因为误操作、SD卡故障或者其他原因。无论是珍贵的照片、还是重要的工作文件,被删除后,我们往往会感到焦虑和失望。相机sd卡中的照片被删除后如何恢复数据?幸…

Windows下安装双版本Python环境安装

前言 根据自己电脑系统选择所需版本进行下载,本次以Windows11环境为展示案例 本机系统查看 例如Windows11,进入系统即可查看本机信息 Python环境安装 Python下载 Python 3 下载 Python 2 下载,在历史版本中找到Python 2 最新版进行下载…

YOLOv7-Openvino和ONNXRuntime推理【CPU】

纯检测系列: YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv7-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 跟踪系列: YOLOv5/6/7-O…

vscode 生成树状图工具:project-tree

按下快捷键“CtrlShiftP”, 在弹框中输入 Project Tree,然后敲回车即会在根目录自动生成README.md(如果之前没有的话)。

[题解]无厘头题目——无聊的军官

这道题非常无厘头! 题目描述: 每个学年的开始,高一新生们都要进行传统的军训。今年有一个军训教官十分奇怪,他为了测试学员们的反应能力,每次吹哨后学员们都会变换位置。每次左数第I位学员都会站到第ai个位置&#x…

谷歌的后量子密码学威胁模型

1. 引言 若现在不使用量子安全算法来加密数据,能够存储当前通信的攻击者最快十年内就能对其解密。这种先存储后解密的攻击是当前采用后量子密码学 (post-quantum cryptography,PQC) 背后的主要动机,但其他未来的量子计算威胁也需要一个深思熟…

Linux下Arthas(阿尔萨斯)的简单使用-接口调用慢排查

使用环境 k8s容器内运行了一个springboot服务,服务的启动方法是main()方法 下载并启动 arthas curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar选择应用 java 进程 就一个进程org.apache.catalina.startup.Bootstrap,输…

Unity PS5开发 天坑篇 之 申请开发者与硬件部署01

腾了好几天终于把PS5开发机调试部署成功, 希望能帮到国内的开发者, 主机游戏PlayStation/Nintendo Switch都是比较闭塞的,开发者账号是必须的。 开发环境有两个部分,一是DEV Kit 开发机, TEST Kit测试机两部分组成,二是Unity的支持库(安装后…

Android的三种动画详解(帧动画,View动画,属性动画)

Android的三种动画详解(帧动画、View动画、属性动画)_android动画效果大全-CSDN博客 1、帧动画 缺点是:占用内存较高,播放的是一帧一帧的图片,很少使用。 顺序播放预先定义的图片,类似于播放视频。 步骤…

数据结构 第3章:栈与队列

文章目录 1. 栈1.1 栈的基本概念1.2 栈的基本操作1.3 栈的顺序存储实现1.4 栈的链式存储实现 2. 队列2.1 队列的基本概念2.2 队列的基本操作2.3. 队列的顺序存储实现2.4 队列的链式存储实现2.5 双端队列 3. 栈与队列的应用3.1 栈在括号匹配中的应用3.2 栈在表达式求值中的应用3…

k8s的pod和svc相互访问时网络链路解析

k8s的pod和svc相互访问时网络链路解析 1. k8s环境中pod相互访问1.1. k8s中pod相互访问的整体流程1.2. k8s的相同机器的不同pod相互访问1.3. k8s的不同机器的不同pod相互访问 2. k8s访问svc2.1 nat操作2.2 流量进入到后端pod 3. 疑问和思考3.1 访问pod相互访问为什么不用做nat?…

【Linux】从零开始认识进程 — 前篇

我从来不相信什么懒洋洋的自由。我向往的自由是通过勤奋和努力实现的更广阔的人生。。——山本耀司 从零开始认识进程 1 认识冯诺依曼体系2 操作系统3 进程3.1 什么是进程???3.2 进程管理PCB 3.3 Linux中的进程深入理解 3.4 进程创建总结 送给…

【vue baidu-map】实现百度地图展示基地,鼠标悬浮标注点展示详细信息

实现效果如下&#xff1a; 自用代码记录 <template><div class"map" style"position: relative;"><baidu-mapid"bjmap":scroll-wheel-zoom"true":auto-resize"true"ready"handler"><bm-mar…