2、架构-服务间的通信

        远程服务将计算机程序的工作范围从单机扩展至网络,从本地延 伸至远程,是构建分布式系统的首要基础。而远程服务又不仅仅是为 分布式系统服务的,在网络时代,浏览器、移动设备、桌面应用和服 务端的程序,普遍都有与其他设备交互的需求,所以今天已经很难找 到没有开发和使用过远程服务的程序员了,但是没有正确理解远程服 务的程序员却不少。

1、 远程服务调用

        远程服务调用(Remote Procedure Call,RPC)在计算机科学中 已经存在超过四十年时间,但在今天仍然可以在各种论坛、技术网站 上遇见“什么是RPC”“如何评价某某RPC技术”“RPC更好还是REST更 好”之类的问题,仍然有新的不同形状的RPC轮子被发明制造出来,仍 然有层出不穷的文章去比对Google gRPC、Facebook Thrift等各家的 RPC组件库的优劣。

2、进程间通信

尽管今天的大多数RPC技术已经不再追求这个目标了,但不可否 认,RPC出现的最初目的,就是为了让计算机能够与调用本地方法一样 去调用远程方法。

3、通信的成本

        1987年,在“透明的RPC调用”一度成为主流范式的时候,Andrew Tanenbaum教授曾发表论文“A Critique of The Remote Procedure Call Paradigm”[1],对这种透明的RPC范式提出一系列质问。

  • 两个进程通信,谁作为服务端,谁作为客户端?
  • 怎样进行异常处理?异常该如何让调用者获知?
  • 服务端出现多线程竞争之后怎么办?
  • 如何提高网络利用的效率?连接是否可被多个请求复用以减少 开销?是否支持多播?
  • 参数、返回值如何表示?应该有怎样的字节序?
  • 如何保证网络的可靠性?调用期间某个链接忽然断开了怎么 办?
  • 发送的请求服务端收不到回复怎么办?

论文的中心观点是:把本地调用与远程调用当作同样的调用来处 理,这是犯了方向性的错误,把系统间的调用透明化,反而会增加程 序员工作的复杂度。

最终,到1994年至1997年间,由ACM和Sun院士Peter Deutsch、套接字接口发明者Bill Joy、Java之父James Gosling等一 众在Sun公司工作的专家们共同总结了通过网络进行分布式运算的八宗 罪(8 Fallacies of Distributed Computing)[2]。

1)The network is reliable.——网络是可靠的。

2)Latency is zero.——延迟是不存在的。

’3)Bandwidth is infinite.——带宽是无限的。

4)The network is secure.——网络是安全的。

5)Topology doesn’t change.——拓扑结构是一成不变的。

6)There is one administrator.——总会有一个管理员。

7)Transport cost is zero.——不必考虑传输成本。

8)The network is homogeneous.——网络都是同质化的。

4、三个基本问题

1.如何表示数据

        这里的数据包括传递给方法的参数以及方法执行后的返回值。无 论是将参数传递给另外一个进程,还是从另外一个进程中取回执行结 果,都涉及数据表示问题。对于进程内的方法调用,使用程序语言预 置和程序员自定义的数据类型,就很容易解决数据表示问题;对于远 程方法调用,则完全可能面临交互双方各自使用不同程序语言的情 况,即使只支持一种程序语言的RPC协议,在不同硬件指令集、不同操 作系统下,同样的数据类型也完全可能有不一样的表现细节,譬如数 据宽度、字节序的差异等。有效的做法是将交互双方所涉及的数据转 换为某种事先约定好的中立数据流格式来进行传输,将数据流转换回 不同语言中对应的数据类型来使用。这个过程说起来拗口,但相信大 家一定很熟悉,就是序列化与反序列化。每种RPC协议都应该要有对应 的序列化协议。

2.如何传递数据

        如何传递数据,准确地说,是指如何通过网络,在两个服务的 Endpoint之间相互操作、交换数据。这里“交换数据”通常指的是应 用层协议,实际传输一般是基于TCP、UDP等标准的传输层协议来完成 的。两个服务交互不是只扔个序列化数据流来表示参数和结果就行, 许多在此之外的信息,譬如异常、超时、安全、认证、授权、事务 等,都可能产生双方需要交换信息的需求。

3.如何表示方法

        确定表示方法在本地方法调用中并不是太大的问题,编译器或者 解释器会根据语言规范,将调用的方法签名转换为进程空间中子过程 入口位置的指针。不过一旦要考虑不同语言,事情又立刻麻烦起来, 每种语言的方法签名都可能有差别,所以“如何表示同一个方法” “如何找到对应的方法”还是需要一个统一的跨语言的标准才行。这 个标准可以非常简单,譬如直接给程序的每个方法都规定一个唯一 的、在任何机器上都绝不重复的编号,调用时压根不管它是什么方 法、签名是如何定义的,直接传这个编号就能找到对应的方法。

5、分裂的RPC

        由于一直没有一个同时满足以上三点的“完美RPC协议”出现,所 以远程服务器调用这个小小的领域,逐渐进入群雄混战、百家争鸣的 战国时代,距离“统一”越来越远,并一直延续至今。现在,已经相 继出现过RMI(Sun/Oracle)、Thrift(Facebook/Apache)、 Dubbo(阿里巴巴/Apache)、gRPC(Google)、Motan1/2(新浪)、 Finagle(Twitter)、brpc(百度/Apache)、.NET Remoting(微 软)、Arvo(Hadoop)、JSON-RPC 2.0(公开规范,JSON-RPC工作 组)等难以穷举的协议和框架。

        这些RPC功能、特点不尽相同,有的是 某种语言私有,有的支持跨越多种语言,有的运行在应用层HTTP协议 之上,有的直接运行于传输层TCP/UDP协议之上,但并不存在哪一款是 “最完美的RPC”。今时今日,任何一款具有生命力的RPC框架,都不 再去追求大而全的“完美”,而是以某个具有针对性的特点作为主要 的发展方向,举例分析如下。

  • 朝着面向对象发展,不满足于RPC将面向过程的编码方式带到 分布式,希望在分布式系统中也能够进行跨进程的面向对象编程,代 表为RMI、.NET Remoting,之前的CORBA和DCOM也可以归入这类。 这种方式有一个别名叫作分布式对象(Distributed Object)。
  • 朝着性能发展,代表为gRPC和Thrift。决定RPC性能的主要因素 有两个:序列化效率和信息密度。序列化效率很好理解,序列化输出 结果的容量越小,速度越快,效率自然越高;信息密度则取决于协议 中有效负载(Payload)所占总传输数据的比例大小,使用传输协议的 层次越高,信息密度就越低,SOAP使用XML拙劣的性能表现就是前 车之鉴。gRPC和Thrift都有自己优秀的专有序列化器,而传输协议方 面,gRPC是基于HTTP/2的,支持多路复用和Header压缩,Thrift则直 接基于传输层的TCP协议来实现,省去了应用层协议的额外开销。
  • 朝着简化发展,代表为JSON-RPC,说要选功能最强、速度最快 的RPC可能会很有争议,但选功能弱的、速度慢的,JSON-RPC肯定会 是候选人之一。牺牲了功能和效率,换来的是协议的简单轻便,接口 与格式都更为通用,尤其适合用于Web浏览器这类一般不会有额外协 议支持、额外客户端支持的应用场合。

        经历了RPC框架的“战国时代”,开发者们终于认可了不同的RPC 框架所提供的特性或多或少是有矛盾的,很难有某一种框架能满足所 有需求。若要朝着面向对象发展,就注定不会太简单,如建Stub、 Skeleton就很烦了,即使由IDL生成也很麻烦;功能多起来,协议就会 更复杂,效率一般也会受影响;要简单易用,那很多事情就必须遵循 约定而不是自行配置;要重视效率,那就需要采用二进制的序列化器 和较底层的传输协议,支持的语言范围容易受限。也正是每一种RPC框 架都有不完美的地方,所以才导致不断有新的RPC轮子出现,也决定了 在选择框架时,在获得一些利益的同时,要付出另外一些代价。 到了最近几年,RPC框架有明显向更高层次(不仅仅负责调用远程 服务,还管理远程服务)与插件化方向发展的趋势,不再追求独立地 解决RPC的全部三个问题(表示数据、传递数据、表示方法),而是将 一部分功能设计成扩展点,让用户自己选择。框架聚焦于提供核心 的、更高层次的能力,譬如提供负载均衡、服务注册、可观察性等方 面的支持。这一类框架的代表有Facebook的Thrift与阿里的Dubbo,尤 其是断更多年后重启的Dubbo表现得更为明显。Dubbo默认有自己的传 输协议(Dubbo协议),同时也支持其他协议;默认采用Hessian 2作 为序列化器,如果你有JSON的需求,可以替换为Fastjson,如果你对 性能有更高的追求,可以替换为Kryo、FST、Protocol Buffers等效率 更好的序列化器,如果你不想依赖其他组件库,也可以直接使用JDK自 带的序列化器。这种设计在一定程度上缓和了RPC框架必须取舍、难以 完美的缺憾。 最后,笔者提个问题,大家不妨来反思一下:开发一个分布式系 统,是不是就一定要用RPC呢?RPC的三大问题源自于对本地方法调用 的类比模拟,如果我们把思维从“方法调用”的约束中挣脱,那在解 决参数与结果如何表示、数据如何传递、方法如何表示这些问题时都 会有焕然一新的视角。

6、REST设计风格

REST(Representational State Transfer)设计风格是由Roy Fielding在2000年他的博士论文中首次提出,用于指导网络应用的架构设计。REST是一种基于资源的架构风格,主要用于网络服务的设计和开发,它强调网络应用应当被视为资源的集合,并通过标准的HTTP方法进行操作。

REST的主要特征

  1. 资源导向:REST将应用中的各种内容视为资源,每个资源在网络上有唯一的URI(统一资源标识符)进行标识。
  2. 无状态操作:REST要求所有的请求从客户端到服务器都包含执行操作所需的所有信息,服务器不会保存任何客户端请求的状态信息,这使得REST服务易于扩展。
  3. 表现层状态转换:尽管REST服务是无状态的,但数据(资源)的表现形式可以根据需要在客户端和服务器之间转换,如XML、JSON等格式。
  4. 统一接口:REST使用统一的接口(比如HTTP的GET、POST、PUT、DELETE方法),使得与资源的交互变得标准化和简化。
  5. 可缓存的:REST允许响应数据被标记为可缓存的或不可缓存的。如果响应是可缓存的,客户端缓存机制可以根据需要重用响应数据。
  6. 按需代码(可选):服务器可以临时扩展或定制客户端的功能,通过传送可执行代码的方式(例如JavaScript),但这不是必需的。

REST与RPC的不同

REST和RPC(Remote Procedure Call)都是实现网络服务的流行方法,但它们在设计和使用上有显著的不同:

  1. 设计哲学

    • REST:基于资源的架构,每个URL代表一个资源,HTTP动词定义对资源的操作。它侧重于资源的状态和表现层的状态转换。
    • RPC:更像是在网络上调用方法。RPC隐藏了网络调用的复杂性,使远程服务器上的函数调用看起来像是本地调用。
  2. 通信方式

    • REST:使用HTTP标准方法(如GET、POST、PUT、DELETE)来执行对资源的操作。
    • RPC:可以使用HTTP POST或其他协议如gRPC(基于HTTP/2),并且通常调用特定的操作或服务方法。
  3. 用例适应性

    • REST:非常适合对资源进行标准操作的应用场景,如Web服务和公开API,其中资源是明确的,标准HTTP方法足以表达所有操作。
    • RPC:适用于需要明确操作和远程过程调用的场景,如内部服务通信,或者当操作不容易映射到标准HTTP方法时。
  4. 可缩放性和灵活性

    • REST:通过其无状态和可缓存的特性,具有较好的可扩展性和互联网级的缓存支持。
    • RPC:虽然可能不如REST缓存友好,但它可以提供更优化的性能和更紧密的服务集成。

总结来说,REST是一种更高层次的、基于资源的网络服务设计方法,强调资源的通用访问和操作的标准化。而RPC则侧重于效率和功能的直接调用,更适合对性能和紧密集成有较高要求的系统。选择哪种技术取决于具体的应用需求和场景。

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

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

相关文章

分布式搜索-elaticsearch基础 安装es

这里是在虚拟机的Linux系统里安装es的教程: 1.创建网络 在Finashell终端输入指令 docker network create es-net 2.将es.tar安装包放入tmp的目录下 输入指令加载镜像:docker load -i es.tar 3.再运行docker 命令 docker run -d \--name es \-e "ES_JAVA_O…

UE4_照亮环境_光束light beam

学习笔记,不喜勿喷,侵权立删!祝愿生活越来越好! 光束:模拟大气中散射的光线。利用定向光源模拟真实曙暮光效果或大气散射的阴影,即可生成 光束 。这些光线为场景添加深度和真实度。 一:一些参数…

RabbitMQ部署指南.md

RabbitMQ部署指南 1.单机部署 我们在Centos7虚拟机中使用Docker来安装。 1.1.下载镜像 方式一:在线拉取 docker pull rabbitmq:3.8-management方式二:从本地加载 在课前资料已经提供了镜像包: 上传到虚拟机中后,使用命令加载…

ASP.NET银行大厅自助信息系统的开发与实现

摘 要 本毕业设计在基于银行业务大厅现有业务的基础上,针对自助银行的概念和其独有特点,通过.NETSQL技术,开发一个简单的银行大厅自助信息系统,完成一些自助银行的业务需求如帐户信息查询、帐户挂失、自助交费、留言、新闻查询…

jmeter中java请求,解决不支持协议和元件,实现自定义元件

目录 java请求 作用场景 JavaTest类源码分析 编写java请求样例 新建java工程,导入jmeter主要依赖。 编写java请求类,继承AbstractJavaSamplerClient, 导入工程为jar包,放置jmeter安装目录下lib/ext目录 重启jmeter,添加ja…

3D,点云下采样

文章目录 一、随机采样1、算法原理2、步骤二、格点采样格点采样的特点三、均匀采样1、类似体素网格采样2、固定间隔采样3、最远点采样四、曲率采样曲率采样的特点:参考资料:对于大规模点云处理而言,直接对点云进行特征提取能较好地保留三维结构信息。但由于点云的无序性,直…

flutter开发实战-log日志存储zip上传,发送钉钉机器人消息

flutter开发实战-log日志存储zip上传,发送钉钉机器人消息 当我们需要Apk上传的时候,我们需要将日志打包并上传到七牛,上传之后通过钉钉通知我们日志下载地址。 这里我使用的是loggy来处理日志 一、引入loggy日志格式插件 在工程的pubspec.…

【经验总结】超算互联网服务器 transformers 加载本地模型

1. 背景 使用 超算互联网 的云服务,不能连接外网,只能把模型下载到本地,再上传上去到云服务。 2. 模型下载 在 模型中 https://huggingface.co/models 找到所需的模型后 点击下载 config.json pytorch_model.bin vocab.txt 3. 上传模型文…

Flutter 中的 CupertinoAlertDialog 小部件:全面指南

Flutter 中的 CupertinoAlertDialog 小部件:全面指南 在Flutter中,CupertinoAlertDialog是用于在iOS风格的应用中显示警告或提示信息的模态对话框。它以其圆角卡片和模糊背景为特点,为用户提供了一个简洁而直观的交互界面。CupertinoAlertDi…

IT行业找工作十面十败,不妨试试鸿蒙开发岗~

近期某脉上看到这样一则帖子,讨论的非常激烈! 相信也有不少人有和他这情况类似,像他这种失业的状态,近两年大家或多或少都深有体验。由于互联网行业进过了十几年的快速发展,从2G→3G→4G→5G,在这个期间人们…

c++ 获取机器码

看到网上代码代码都没什么好的&#xff0c;自己备用一个 #include <iostream> #include <string> #include <sstream> #include <iomanip> #include <Windows.h> #include <iphlpapi.h> // 包含这个头文件以获取 PIP_ADAPTER_INFO #inclu…

elasticsearch-head 源码运行

1、下载安装nodejs 地址&#xff1a;Node.js — Run JavaScript Everywhere 2、git下载 elasticsearch-head 源码 地址&#xff1a;GitHub - mobz/elasticsearch-head: A web front end for an elastic search cluster 3、使用cmd 进入 elasticsearch-head 目录 4、依次执…

嵌入式学习-M4的基本定时器

基本介绍 框图分析 时钟选择 计数器结构 开启重装载值寄存器的影子寄存器的工作时序图 未开启重装载值寄存器的影子寄存器的工作时序图 更新事件以及中断 相关寄存器 相关库函数

Cesium+山海鲸:可视化技术的完美融合

在当今数字化浪潮中&#xff0c;可视化技术已经成为各个行业提升效率和优化决策的关键。特别是在地理信息系统&#xff08;GIS&#xff09;和数字孪生领域&#xff0c;这种技术的重要性更加凸显。而山海鲸可视化与Cesium的融合&#xff0c;无疑是这一领域的重大突破。 首先&am…

【Spring】BeanFactory源码翻译

package org.springframework.beans.factory;import org.springframework.beans.BeansException; import org.springframework.core.ResolvableType; import org.springframework.lang.Nullable;/*** The root interface for accessing a Spring bean container.* 用于访问Spri…

量化交易:Dual Thrust策略

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; Dual Thrust策略起源于20世纪80年代&#xff0c;由美国著名交易员和金融作家Larry Williams首次提出。这一策略的核心思想是通过捕捉市场中的短期波动来实现盈利。Larry Williams通过多年的研究和实践&#xff0c;发…

智能EDM邮件群发工具哪个好?

企业之间的竞争日益激烈&#xff0c;如何高效、精准地触达目标客户&#xff0c;成为每个市场战略家必须面对的挑战。在此背景下&#xff0c;云衔科技凭借其前沿的AI技术和深厚的行业洞察&#xff0c;匠心推出了全方位一站式智能EDM邮件营销服务平台&#xff0c;重新定义了邮件营…

[ECE] SRAM DRAM

SRAM&#xff08;Static Random-Access Memory&#xff0c;静态随机存取存储器&#xff09;和DRAM&#xff08;Dynamic Random-Access Memory&#xff0c;动态随机存取存储器&#xff09;是两种主要的随机存取存储器技术&#xff0c;它们在计算机和其他电子设备中扮演着重要的角…

2024OD机试卷-字符串序列判定 (java\python\c++)

题目:字符串序列判定 题目描述 输入两个字符串 S 和 L ,都只包含英文小写字母。S长度 ≤ 100,L长度 ≤ 500,000。判定S是否是L的有效子串。 判定规则:S 中的每个字符在 L 中都能找到(可以不连续),且 S 在L中字符的前后顺序与 S 中顺序要保持一致。(例如,S = ” ace…

StringBuilder

demo1 描述&#xff1a; 主要演示了StringBuilder类的使用。 首先创建一个空的StringBuilder对象s。 使用System.out.println()方法打印对象s&#xff0c;输出结果为""&#xff08;空字符串&#xff09;。 调用StringBuilder的append()方法多次&#xff0c;将字符串…