rpc框架的作用,rpc框架实现

推荐学习全网首发!马士兵内部共享—1658页《Java面试突击核心讲》微服务架构秘籍:SpringCloud+SpringCloud Alibaba,全网疯传一

推荐学习

全网首发!马丙胜内部分享—1658页《Java面试突击核心讲》 微服务架构的秘密:SpringCloud+SpringCloud阿里巴巴传遍全网22f0c2f56ee849c280aa10cb87eb263f~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=GhgvHfzlwGFw45%2B3NYRNv0dgIjk%3D

一、REST 与 RPC

1、什么是 REST 和 RPC 协议?

在单个应用中,模块之间的调用是通过编程语言级别的方法函数来实现的,但在分布式系统中,每个服务实例一般都是一个进程,服务需要使用进程间通信。常见的通信协议主要有RPC协议和REST协议。

(1)中断:

REST是基于HTTP实现的,使用HTTP协议来处理数据通信。这是因为任何语言都支持HTTP协议。通用http API 有时称为Rest 接口。 REST 是一种架构风格,指的是一组架构约束和原则,满足REST 原则的应用程序或设计将一切视为资源。 REST强调组件交互的可扩展性、接口的多样性、组件的独立部署、减少交互延迟的中间件,还可以增强安全性和封装遗留系统。

(2)RPC:

RPC 是一种进程间通信方法,允许像调用本地服务一样调用远程服务。大多数通信协议都是二进制的。

2、RPC 与 REST 的对比

6e85760da51e4233a6a9f8c6aa1a0ed3~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=4T1LnULwTW1%2Fa70OVngAOQZD9Rg%3D

(1)传输协议及性能:RPC的传输协议灵活,可以基于TCP实现。由于TCP协议在协议栈中处于较低层,因此协议字段可以更加可定制,并且请求消息可以更小。减少网络开销,提高传输性能,减少传输时间,实现吞吐量和并发性的提高。 REST的HTTP协议是高层协议,因此发送同样的信息时,请求会比使用TCP协议发送时会有更多的无用内容,占用的字节数也会更大。在同一网络内,HTTP 优于基于TCP 的协议,后者传输数据的效率较低且传输时间较长。然而REST的HTTP大部分是通过JSON实现的,序列化消耗了大量的性能。它基于HTTP 2.0,也可以用作RPC。

(2)灵活性、开放性、通用性:REST是通过HTTP实现的,相对标准化,通用性强。虽然无论哪种语言支持HTTP协议,调用和测试REST都非常方便,但是使用RPC时存在很多限制。如果需要对外暴露RPC,需要更多的处理,而且不如REST灵活。

(3)使用场景:REST主要用于对外开放的异构环境,如浏览器接口调用、API接口调用、第三方接口调用等。 RPC主要用于内部服务调用,其性能消耗低、传输效率高,特别适合内部子系统较多、接口较多的大型网站。

二、RPC 框架

REST 和RPC 都常用于微服务架构中。微服务的好处之一是它们不会限制服务提供商对要使用的技术的选择,并实现大型企业中团队之间的技术分离。 然而,在没有统一的通信框架的情况下,各个团队的服务提供者负责一系列的序列化、反序列化、网络框架、连接池、入站和出站线程、超时处理、状态机和其他“外部业务”。必须实施。技术劳动导致整体效率低下。因此,统一的通信框架统一处理上述“非业务”技术劳动,是服务化要解决的主要问题。

1、什么是 RPC 框架?

RPC框架的目标是让远程服务调用更简单、更透明。当使用RPC框架时,开发人员只需要知道谁提供了什么。远程服务接口就足够了,不需要担心底层的通信细节或者调用流程。 RPC框架作为微服务架构的基础组件,可以显着降低微服务架构的成本,提高调用者和服务提供者的研发效率。

2、RPC 框架的技术架构

如下所示,一个典型的RPC使用场景主要包括服务发现、负载、容错、网络传输、序列化等组件。其中“RPC协议”规定了服务如何序列化以及如何序列化。这也是RPC的一个核心特性。

应用级RPC框架:Dubbo、Google gRPC 通信框架:Netty 远程通信协议:RMI、Socket、SOAP (HTTP XML)、REST (HTTP JSON) 36a7b92369044f638f1911af132e97b0~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=CosZ2db4wDpYX1AZuAInGwzbiOc%3D

3、RPC 框架的调用流程

165cd248b5f844948d2e3a1230b8c43e~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=VcBoyCtIzAn0iO0kUO34%2BfIJ34U%3D

3.1. RPC框架的核心组件:

(1) 客户端:调用服务的人。

(2)客户端存根:存储服务器的地址信息,并将客户端的请求参数数据信息封装成网络消息,通过网络传输发送给服务器。

(3) Server Stub:接收客户端发送的请求消息,解压并调用本地服务进行处理。

(4)服务器:服务的实际提供者。

3.2.RPC调用流程:

(1)服务使用者(客户端)通过本地调用来调用自己需要使用的服务。

(2)客户端stub收到调用请求后,将方法、输入参数等信息序列化(组装)成可以通过网络发送的消息体。

(3) 客户端存根找到远程服务地址并通过网络将消息发送到服务器。

(4) Server Stub收到消息后,进行解码并反序列化。

(5) Server Stub根据解码结果调用本地服务进行相关处理。

(6) 服务器执行具体的业务逻辑,并将处理结果返回给服务器存根。

(7) 服务器存根将返回的结果序列化并通过网络发送给消费者。

(8) 客户端存根接收消息,对其进行解码并反序列化。

(9) 服务使用者收到最终结果。

RPC框架的目标是完全封装上面的步骤2-10,即封装调用、编码/解码过程,以便用户可以像调用本地服务一样调用远程服务。这是关于能够做到这一点。

3951e8f9334948f6bd6e983645baee2d~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=BVb3kY9IP7b6Auptm82hrmxpxEc%3D

4、如何实现一个RPC框架?

根据上面的描述,如果想要实现一个RPC框架怎么办?要实现一个RPC框架,只需要解决以下几个基本的事情:

4.1. 网络通信如何工作?

对于远程调用,客户端和服务器之间的通信是基于网络连接的,因此必须先建立通信连接。这会将请求信息字节流式传输到服务器并返回序列化的响应结果。这个通信过程中使用的协议没有限制,只要能够完成传输就可以,但是需要考虑两个问题:如何选择网络协议以及如何建立网络协议。联系。

将对象转换为二进制流的过程称为序列化。将二进制流转换为对象的过程称为反序列化。 RPC有多种可选的网络传输方式,包括TCP和UDP协议。 HTTP 协议。每个协议对整体性能和效率都有不同的影响。那么如何选择正确的网络传输协议呢?要解决这个问题,首先需要了解不同的传输协议如何与RPC 配合使用。

基于TCP 协议的RPC 调用在定制协议字段方面提供了更大的灵活性、更小的请求消息、减少的网络开销、更好的发送性能以及更快的发送时间,因为TCP 协议在协议栈的较低层会缩短。实现更高的吞吐量和并发性。但需要更多关注底层复杂细节,实施成本较高。同时发送请求需要针对Android、iOS等不同平台重新开发不同的工具包。工作量大,难以快速响应用户需求。 RPC基于HTTP协议实现,可以使用JSON和XML格式的请求或响应数据。 JSON和XML是常见的格式标准(使用HTTP协议还需要序列化和反序列化,这不是该协议的问题)。 Web程序已经有了序列化的内容,开源的分析工具也已经相当成熟,使用它们进行二次开发非常方便和容易。但由于HTTP协议是高层协议,发送同样的信息时,请求比使用TCP协议发送的请求有更多的浪费内容和占用更多的字节。在同一网络内,HTTP 比基于TCP 的协议更好,传输数据的效率较低,但当然您可以通过压缩数据来减少这种差异。

5、如何选择正确的PRC网络传输协议?

三、RPC框架dubbo

前面提到,微服务架构中经常使用RPC,而RPC框架作为微服务架构的基础组件,可以显着降低微服务架构的成本,提高调用者和服务的开发效率。提供者。 Dubbo是阿里巴巴开源的基于Java的RPC分布式服务框架,提供高性能、透明的RPC远程服务调用和SOA服务治理解决方案。另外,基于Spring Cloud Ali技术栈的Spring-cloud-alibaba-dubbo,基于Spring Cloud Ali提供的Nacos注册中心,提供了Dubbo和Spring Cloud的集成解决方案。换句话说,Dubbo Spring Cloud 以接近零的成本将您服务内的RPC 协议调用转换为基于RPC 的服务调用。

1、dubbo 是什么?

2.1. 整个销钉过程:

dacb4a8728014012b011eb3a48b7a04f~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=270VWs7cx%2BRKHP6WFRHumtMrreI%3D

紫色虚线:启动时完成的函数蓝色虚线:执行时执行的函数,异步调用蓝色实线:执行时执行的函数,同步调用在2.1.1中,dubbo的整体执行流程解释如下。

(1)启动容器,加载并运行服务提供者。

(2)当服务提供者启动服务时,它在注册中心注册其提供的服务。

(3)服务消费者在启动服务时,向注册中心注册所需的服务。

(4)注册中心向消费者返回服务提供者地址列表。一旦消费者接收到内容发生变化,注册中心就会基于长连接将变化的数据推送给消费者。

(5)服务消费者基于软负载均衡算法从提供者地址列表中选择调用的提供者。如果呼叫失败,请选择其他提供商进行呼叫。

(6)服务使用者和服务提供者将通话次数和通话时长存储在内存中,并每分钟定期向监控中心发送统计数据。

消费者使用代理模式,创建Provider类的代理对象。通过代理对象获取提供者内的实际功能。代理对象负责保护提供者的实际功能。

2.1.2.dubbo的整个执行流程可以理解为生产者/消费者模型+注册中心+监控中心。这样设计的原因是:

消费者和提供者解耦,双方都可以横向增加或减少节点数量。注册中心本身可以是一个点对点集群,如果一个节点出现故障,可以动态添加和减少节点。即使所有注册中心在短时间内出现故障,服务提供商也会变得无国籍。一个宕机了,但是不影响使用

2、dubbo 的执行流程

2.2.1,dowel同步调用流程。

(1) 客户端线程调用远程接口并向服务器发送请求。同时,当前线程必须处于“挂起”状态。也就是说,线程不能向后运行,必须获得下一个结果。在服务器向后运行之前。

(2)服务器收到客户端的请求后,处理该请求并将结果发送给客户端。

(3) 客户端收到结果,当前线程继续执行。

Dabo中使用socket来建立长连接和数据传输,底层与Apache mina框架耦合。 Apache mina框架基于Reactor模型通信框架,基于tcp长连接。 dubbo 使用IoSession.write() 方法进行远程调用和发送消息。该方法的远程调用过程是异步的。即当前线程可以发送请求,稍后再执行。服务器端处理完成后,将服务器端结果以消息的形式发送给客户端。这里出现两个问题。

(1)如何“暂停”当前线程,等待结果返回,然后向后运行:

老师创建了一个对象obj,使用put(ID,obj)将其保存到全局map中,然后使用synchronized获取obj锁,并调用obj.wait()等待当前线程状态。另一个消息监听线程等待,直到服务器收到处理结果。当处理结果到达时,使用map.get(ID)查找obj,然后使用synchronized获取obj锁,并调用obj.notifyAll()唤醒之前的消息。等待线程。

(2)Socket通信是全双工的,当多个线程同时进行远程方法调用时,双方的许多消息可以在客户端和服务器之间的socket连接上来回发送,并且顺序可以颠倒有性别。如果混乱,服务器会向客户端发送结果消息。如何检查哪个消息结果首先被哪个线程调用:

在将其传递给服务器之前,我们使用ID 使其唯一,服务器将其发送回,以便我们知道结果属于哪个线程。

2.2.2. Dubbo同步调用原理:

(1)客户端使用线程调用远程接口,Dubbo使用AtomicLong累加一个从0开始的数字。

(2)将封装好的方法调用信息(被调用者接口名、方法名、参数值列表等)和处理结果回调对象转换为对象。

(3) 将put(ID, object)添加到专门存储调用信息的全局ConcurrentHashMap中。

(4)将ID和封装的方法调用信息封装成connRequest对象,使用IoSession.write(connRequest)异步发送

(5) 然后当前线程尝试使用回调的get() 方法检索远程返回的结果。在get()内部,首先使用synchronized获取回调对象上的锁,并检测是否已检索到结果。如果没有,则调用回调。 wait()方法释放回调锁并使当前线程进入等待状态。

(6) 服务器接收并处理请求后,将结果(包括唯一ID)发送回客户端。客户端socket连接到专门监听消息的线程后,我们分析结果,获取ID,通过前面ConcurrentHashMap中的服务端获取Get(ID)找到回调,取出方法调用的结果. 设置为回调对象。

(7)最后,监听线程获取回调对象callback的同步锁(因为之前调用wait()释放了回调锁),并首先使用notifyAll()唤醒正在运行的线程并继续。如果该方法继续运行,整个过程将在此时终止。

请注意,这里的回调对象是为每次调用创建的新对象,并且不能共享。此外,必须保证ID 是唯一的,至少在套接字连接内是唯一的。

2.2、dubbo 同步调用原理

(1) 随机调用策略(默认):该策略允许您为每个服务器实例设置不同的权重,分配更多的流量。

(2)轮询调用策略:将请求均匀分配到每台机器。如果每台机器的性能不同,性能差的机器的负载往往会重,因此需要调整重量,使性能差的机器的负担更轻。交通阻塞。

(3) Least Active Count Strategy:根据服务器的运行状态选择服务。当特定机器的性能下降时,它收到的请求会减少,性能较差的不活动机器也会增多。分配的请求较少。

(4) 一致的哈希算法:具有相同参数的请求被可靠地分发到固定的服务器节点。如果某个服务器节点发生故障,剩余流量会根据虚拟节点均匀分配,不会出现明显的抖动。

3、dubbo 的负载均衡策略

费洛夫

er(默认):失败自动切换,当出现失败,重试其它服务器,默认为2次。通常用于读操作,但重试会带来更长延迟。
Failfast:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2″ 来设置最大并行数。
Broadcast:广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。

5、dubbo支持哪些协议和适用场景?

(1)dubbo:单一长连接和 NIO 异步通讯,适合大并发小数据量的服务调用,以及消费者远大于提供者的情况。传输协议 TCP,异步 Hessian 序列化。Dubbo 官方推荐使用 dubbo 协议。但是,dubbo 协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低
(2)RMI: 采用 JDK 标准的 RMI 协议实现,使用 Java 标准序列化机制,传输参数和返回参数对象需要实现 Serializable 接口,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议 TCP。多个短连接,基于 TCP 协议传输,同步传输,适用常规的远程服务调用和 RMI 互操作。在依赖低版本的 Common-Collections 包,Java 序列化存在安全漏洞。
(3)WebService:基于 WebService 的远程调用协议,集成 CXF 实现,提供和原生 WebService 的互操作。多个短连接,基于 HTTP 传输,同步传输,适用系统集成和跨语言调用。
(4)HTTP: 基于 Http 表单提交的远程调用协议,使用 Spring 的 HttpInvoke 实现。多个短连接,传输协议 HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器 JS 调用。
(5)Hessian:集成 Hessian 服务,基于 HTTP 通讯,采用 Servlet 暴露服务,Dubbo 内嵌 Jetty 作为服务器时默认实现,提供与 Hession 服务互操作。多个短连接,同步 HTTP 传输,Hessian 序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件。
(6)Redis:基于 Redis 实现的RPC协议。
(7)Memcache:基于 Memcache实现的 RPC 协议。

6、dubbo 的通信框架:

dubbo 默认使用 Netty 作为通讯框架

7、dubbo的架构设计:

b7d168d2ea51428daabe160734ff14f2~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717814933&x-signature=nIQ%2Fl%2FfikD3aZWjInlEOA%2FwwO8g%3D
7.1、图例说明
左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。图中从下至上分为 10 层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于关联各层的实现类。图中蓝色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调时链,紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法。7.2、各层说明:
(1)接口服务层(Service):该层与实际业务逻辑相关,根据 provider 和 consumer 的业务设计对应的接口和实现
(2)配置层(Config):对外配置接口,以 ServiceConfig 和 ReferenceConfig 为中心
(3)服务代理层(Proxy):服务接口透明代理,生成服务的客户端 Stub 和 服务端的 Skeleton,以 ServiceProxy 为中心,扩展接口为 ProxyFactory
(4)服务注册层(Registry):封装服务地址的注册和发现,以服务 URL 为中心,扩展接口为 RegistryFactory、Registry、RegistryService
(5)路由层(Cluster):封装多个提供者的路由和负载均衡,并桥接注册中心,以Invoker 为中心,扩展接口为 Cluster、Directory、Router 和 LoadBlancce
(6)监控层(Monitor):RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory、Monitor 和 MonitorService
(7)远程调用层(Protocal):封装 RPC 调用,以 Invocation 和 Result 为中心,扩展接口为 Protocal、Invoker 和 Exporter
(8)信息交换层(Exchange):封装请求响应模式,同步转异步。以 Request 和Response 为中心,扩展接口为 Exchanger、ExchangeChannel、ExchangeClient 和 ExchangeServer
(9)网络 传输 层(Transport):抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel、Transporter、Client、Server 和 Codec
(10)数据序列化层(Serialize):可复用的一些工具,扩展接口为 Serialization、ObjectInput、ObjectOutput 和 ThreadPool
作者:张维鹏
原文链接:https://blog.csdn.net/a745233700/article/details/122445199

原创文章,作者:小条,如若转载,请注明出处:https://www.sudun.com/ask/85043.html

(0)
小条's avatar小条
上一篇 2024年6月1日 上午10:48
下一篇 2024年6月1日 上午10:49

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注