RPC与REST

RPC与REST

        • 访问远程服务
          • 1远程服务调用(Remote Procedure Call,RPC):RPC 解决什么问题?如何解决的?为什么要那样解决?
            • 1.1 先解决两个进程间如何交换数据的问题,也就是进程间通信(Inter-Process Communication,IPC)。可以考虑的办法有以下几种:
            • 1.2 通信的成本
            • 1.3 三个基本问题
            • 1.4 统一的 RPC 与 分裂的 RPC
          • 2 REST 设计风格
            • 2.1 理解 REST
            • 2.2 RESTful 的系统

访问远程服务

远程服务将计算机的工作范围从单机扩展到网络,从本地延伸至远程,是构建分布式系统的首要基础。

而远程服务又不仅仅是为了分布式系统服务的,在网络时代,浏览器、移动设备、桌面应用和服务端的程序,普遍都有与其他设备交互的需求,所以今天很难找到没有开发过远程服务的人,但是没有正确理解远程服务的coder比比皆是。

1远程服务调用(Remote Procedure Call,RPC):RPC 解决什么问题?如何解决的?为什么要那样解决?

进程间通信:尽管今天的大多数RPC 已经不再追求这个目标了,但无可否认,在最初的时候,这是先要解决的:让调用远程方法和本地方法一样。

1.1 先解决两个进程间如何交换数据的问题,也就是进程间通信(Inter-Process Communication,IPC)。可以考虑的办法有以下几种:
  1. 管道或具名管道:管道类似于两个进程间的桥梁,可通过管道在进程间传递 少量的字符流或字节流。普通管道只用于有亲缘关系的进程(由一个进程启动的另外一个进程)间通信。具名管道拜托了普通管道没有名字的限制,除具有普通管道的所有功能外,它还允许无亲缘关系进程间的通信。管道典型的应用就是命令行中的 | 操作符,如:ps -ef | grep java ps 与 grep 都有独立的进程,以上命令就是将ps 的标准输出链接到grep 的标准输入上。
  2. 信号(signal):用于通知目标进程有某事发生,除了用于进程间通信外,进程还可以发送信号给进程自身。信号的典型命令就是 kill 命令:kill -9 pid
  3. 信号量(Semaphore):信号量用于两个进程间同步协作手段,它相当于操作系统提供的一个特殊变量,程序可以在上面进行 wait() notify() 操作。
  4. 消息队列:以上三种方式只适合传递少量信息,消息队列用于进程间数据量较多的通信。进程可以向队列添加消息,被赋予读权限的进程可以消费消息,MQ 克服了信号承载量小,管道只能用于无格式字节流以及缓冲区大小受限的缺点,但实时性相对受限。
  5. 共享内存(Shared Memory) :允许多个进程访问同一块公共的内存空间,这是效率最高的进程间通信方式。当一块进程被多进程共享时,各个进程往往会与其他通信机制,如信号量结合使用。
  6. 套接字接口(Socket):消息队列和共享内存只适合于单机多进程间的通信,套接字接口是更为普适的进程间通信机制,可用于不同机器之间的进程通信。套接字(socket)当仅限于本机进程间通信时,套接字接口是优化过的,不会经过网络协议栈,不需要打包拆包、计算校验和等,只是简单的将应用层数据从一个进程拷贝到另一个进程。这种进程间通信叫 IPC Socket。
1.2 通信的成本

IPC Socket 不仅适用于本地相同机器间不同进程间的通信,由于 Socket 网络栈的统一接口,它也理所应当的能支持基于网络的跨机器进程间通信。这么做有一个看起来无比诱人的好处,由于 Socket 是各个操作系统都有提供的标准接口,完全有可能把远程方法调用的通信细节隐藏在操作系统底层,从应用层面商看来可以做到远程调用与本地的进程间通信在编码上完全一致。事实上,在原始分布式时代的确是这么用的,但这种透明的调用形式却反问滥用以至于显著降低了分布式系统的性能。
所以,对 RPC 提出一系列的疑问:

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

这里的中心观点是:本地调用与远程调用当做一样处理,这是犯了方向性的错误。
Sun 公司的一众大佬们总结了通过网络记性分布式运算的八宗罪:

  1. 网路是可靠的,安全的,同质化的;(这是三点)
  2. 延迟是不存在的;
  3. 带宽是无限的;
  4. 拓扑结构是一成不变的;
  5. 总会有一个管理员;
  6. 不必考虑传输成本。

以上八大问题潜台词就是说如果远程服务调用要弄透明化的话,就必须为这些罪过埋单(就是RPC不能透明化)。这算是给 RPC 是否能等同于 IPC 正式定下了一个具有公信力的结论。至此,RPC 应该是一种高层次的或者说语言层次的特征,而不是像 IPC 那样,是低层次的货系统层次的特征成为工业界、学术界的主流观点

RPC 的定义:远程服务调用是指位于互不重合的内存地址空间中的两个程序,在语言层面上,以同步的方式使用有限带宽的信道来传输程序控制信息。

1.3 三个基本问题

RPC 协议无外乎变着花样使用各种手段来解决以下三个基本问题:

  • 如何表示数据:这里的数据包含了传递给方法的参数,以及方法执行后的返回值。不同进程间数据读取问题。且 RPC 完全可能绵连交互双方各自使用不同程序语言的情况:即使是用了相同语言的 RPC 协议,在不同硬件指令集、不同OS下,同样的数据类型也完全可能有不一样的表现细节,如数据宽度、字节差异等。有效的做法是:将交互双方所涉及的数据转换为某种事先约定好的中立数据流格式来进行传输,将数据流转换回不同语言中对应的数据类型来进行使用,就是序列化与反序列化。每种 RPC 协议都要有对应的序列化协议,如 gRPC Protocol Buffers,其他众多轻量级 RPC 的 JSON Serialization。
  • 如何传输数据:指如何通过网路,在两个服务的 Endpoint 间相互操作、交换数据。这里的“交换数据”通常指的是应用层协议,实际传输一般是基于标准的 TCP、UDP 等标准的传输层协议来完成的。两个服务交互不只是扔个序列化数据就行,还需有异常、超时、安全、认证、授权、事务等,这些都可能是双方需交换的。这类数据叫:Wire Protocol。常见的有:Java RMI 的 JRMP,Web Service 的 SOAP,如果要求足够简单,双方都是 HTTP Endpoint,就可直接使用 HTTP 协议(如 JSON-RPC)。
  • 如何确定方法:这在本地方法调用中不是太大问题,编译器会根据语言规范,将调用的方法签名转换为进程空间中子过程入口位置的指针。不过一旦要考虑不同语言事情又麻烦起来,每门语言的方法前面可能不同,所以“如何表示同一个方法”,“找到对应的方法”还是得弄个跨语言的统一标准。这个标准非常简单,如直接给程序的每个方法都规定一个唯一的、在任何机器上都绝不重复的编号,直接找对应方法。这是当初DCE 的解决方案,就是 UUID,虽然此后DCE 还是弄了一套语言无关的接口描述语言(Interface Description Language,IDL),但 UUID 却广为流传。用于表示方法的协议:Web Service 的 WSDL,JSON-RPC 的JSON-WSP。
1.4 统一的 RPC 与 分裂的 RPC

刚开始的时候,大家总是尝试 RPC 可以解决所有分布式问题,如刚开始的时候既要支持面向对象,又要支持多种语言,功能还齐全。但是没有一家成功的,简单、普适、高性能这三点,似乎真的难以同时满足。所以现在的 RPC 仍处于百家争鸣的时代,大家都不再去追求大而全的“完美”,而是有自己的针对性作为主要的发展方向。如:

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

到了最近几年,RPC 框架有明显的朝着更高层次(不仅负责调用远程服务,还要管理远程服务)与插件化方向发展的趋势,不再追求独立地解决 RPC 的全部三个问题(表示数据、传递数据、表示方法),而是将一部分功能设计成扩展点,让用户自己去选择。框架聚焦于提供核心的、更高层次的能力,如提供负载均衡、服务注册、可观察性等方面的支持。这一类框架的代表有 Facebook 的 Thrift 和阿里的 Dubbo。尤其是断更多年后重启的 Dubbo 表现得更为明显,它默认有自己的传输协议(Dubbo协议),同时也支持其他协议;默认采用 Hessian2 作为序列化器,如果你有 JSON 需求,可以替换为 Fastjson,如你对性能有更高的追求,可以替换为 Kryo、Protocol Buffers 等效率更好的序列化器,如果你不想依赖其他组件库,直接使用 JDK 自带的序列化器也是可以的。

开发一个分布式系统,是不是一定要用 RPC 呢?

2 REST 设计风格

很多人会拿 REST 与 RPC 互相比较,其实,REST 无论是在思想上、概念上,还是适用范围上,与 RPC 都不尽相同,充其量只能算有些相似,但本质上并不是同一类型的东西。

2.1 理解 REST

个人会有好恶偏爱,但计算机科学是务实的,有了RPC还会提出REST,有了面向过程编程还能产生面向资源编程,后者总会有些前者没有的闪光点,我们先理解 REST,在谈论评价它。
比较容易理解 REST 思想的途径是先理解什么是 HTTP,再配合一些实际例子来进行类比,你会发现REST(Representational State Transfer)实际是 HTT(Hypertext Transfer)的进一步抽象,两者就如同接口与实现类的关系一般。

Hypertext 超文本一词已被普遍接受,它指的是能够进行分支判断和差异响应的文本,相应地,超媒体指的是能够进行分支判断和差异响应的图形、电影和声音(也包括文本)的复合体。就是指文字可以点击、可以出发脚本等。

下面从“超文本”或“超媒体”的含义来理解 REST 中的相关概念:

  • 资源(Resource)比如你在阅读的一篇文章,其内容本身就是资源;

  • 表征(Representation)当你通过电脑浏览阅读此文章时,浏览器向服务端发出请求“我需要这个资源的HTML 格式”,服务端向浏览器返回的这个 HTML 就是表征,或者是文本的 PDF、Markdown等都是,即表现形式。

  • 状态(State)当你读完了这篇文章,想看后面是什么内容时,你想服务器发送“下一篇文章”的请求,但服务端不知道下一篇是哪一篇,就得根据你现在的上下文信息来判断,以来的就是状态;

  • 转移(Transfer)无论状态是由服务端还是客户端来提供,“取下一篇文章”这个行为必然只能由服务端来提供,服务端通过某种形式,把当前文章转变为下一篇,这就叫“表征状态转移”。

  • 统一接口(Uniform Interface)前面提到的下一篇的点击跳转,这是一种让表征状态发生转移的方式,但是 URI 的含义是统一资源标识符,是一个名词,如何表达出“转移”的含义的呢?答案是 HTTP 协议中已经提前约定好了一套“统一接口”,它包括:GET、HEAD POST PUT DELETE TRACE OPTIONS七种基本操作,任何一个支持 HTTP协议的服务器都会遵守这套规定,对特定的 URI 采取这些操作,服务器就会触发相应的表征状态转移的动作。

  • 超文本驱动(Hypertext Driven)任何网站的导航(状态转移)行为都不可能是预置于浏览器代码之中,而是由服务器发出的请求响应信息(超文本)来驱动的。

  • 自描述信息 消息的类型以及应如何处理这条消息。如 Content-Type:application/json;charset=utf-8

2.2 RESTful 的系统

理解了上面的概念,我们就可以开始讨论面向资源的呢编程思想与几个具体的软件架构设计原则了。一套完整的、完全满足 REST 风格的系统应满足以下六大原则:

  1. 服务端与客户端分离(Client-Server)将用户界面所关注的逻辑和数据存储所关注的逻辑分离开来,有助于提高用户界面的跨平台的可移植性。
  2. 无状态(Stateless)无状态是 REST 的一条核心原则,部分开发者在做接口规划时,觉得 REST 风格的服务怎么设计都感觉别怒,很有可能的一种原因是在服务端持有着比较重的状态。应由客户端承担状态维护职责,但目前大多数系统都达不到这个要求。
  3. 可缓存(Cacheability)无状态服务虽然提升了系统的可见性、可靠性和可伸缩性,但降低了系统的网络性。“降低网络性”是指某个功能如果使用有状态的设计只需一次(或少量)请求即可完成,而无状态的得多次。为了缓解这个矛盾,REST 希望软件系统能入万维网一样,允许客户端和中间的通讯传递者(如代理)将部分服务端的应答缓存起来。
  4. 分层系统(Layered System)这里的分层并不是表示层、服务层、持久层这种,而是客户端一般不用知道是否直接连接到了最终的服务器,或中间服务器。中间服务器可以通过负载均衡和共享缓存的机制提高系统的可扩展性,这样也便于缓存、伸缩和安全策略的部署。该原则的典型应用是内容分发网络。如我们浏览某个网站,并不是直接访问源服务器,而是访问了某个 CDN 服务器。
  5. 统一接口(Uniform Interface)这是 REST 的另一条核心原则,REST 希望开发者面向资源编程,希望软件系统设计的重点放在抽象系统该有哪些资源上,而不是抽象系统该有哪些行为上。这条原则可以类比计算机中对文件管理的操作来理解,管理文件的操作是可数的,而且对所有文件都是固定的,统一的。如果面向资源来设计系统,同样会有类似的操作特征,所有这些操作都借用了HTTP协议中固有的操作命令来完成。因为面向资源编程的抽象程度更高。想要在架构设计中合理恰当的利用统一接口,系统应能做到每次请求中都包含资源的ID,所有操作均通过资源ID 来进行;建议每个资源都是自描述的消息;建议通过超文本来驱动应用状态的转移
  6. 按需代码(Code-On-Demand)可选原则。

本节开篇提出的 REST 与 RPC 在思想上的差异?
REST 的基本思想是面向资源来抽象问题,它与此前流行的面向过程的编程在抽象主体上有本质区别。在 REST 提出以前,人们设计分布式系统的唯一方案就只有 RPC,开发者是围绕着“远程方法”去设计两个系统交互的,这样做的坏处不仅是“如何在不同系统间表示一个方法”、“如何获得接口能够提供的方法清单”都成了需要专门协议去解决的问题,更在于服务的每个方法都是独立的,服务者必须熟悉每个方法才能使用,而REST抽象为了几类

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot后端验证码-防止密码爆破功能

一、简介 为了防止网站的用户被通过密码典爆破。引入验证码的功能是十分有必要的。而前端的验证码又仅仅是只防君子不防小人。通过burpsuit等工具很容易就会被绕过。所以后端实现的验证码才是对用户信息安全的一大重要保障。 实现思路: 1.引入图形生成的依赖 2.生成…

VPN 的入门介绍

VPN(虚拟专用网络) 简介 虚拟专用网络,简称虚拟专网(VPN),其主要功能是在公用网络上建立专用网络,进行加密通讯。在企业网络中有广泛应用。VPN网关通过对数据包的加密和数据包目标地址的转换实…

SpringBoot日常:封装rabbitmq starter组件

文章目录 逻辑实现RabbitExchangeEnumRabbitConfigRabbitModuleInfoRabbitModuleInitializerRabbitPropertiesRabbitProducerManagerPOM.xmlspring.factories 功能测试application.yml配置生产者:消费者:测试结果:总结 本章内容主要介绍编写一…

【电机控制】EG2134无刷电机驱动、控制一体板——开环、无感SMO验证

【电机控制】EG2134无刷电机驱动、控制一体板——开环、无感SMO验证 文章目录 前言一、硬件二、软件三、开环SVPWM四、SMO无感观测器闭环控制五、参考文献总结 前言 【电机控制】直流有刷电机、无刷电机汇总——持续更新 【电机控制】EG2134无感FOC驱控一体板-滑模观测器 使用…

C++11中新特性介绍-之(二)

11.自动类型推导 (1) auto类型自动推导 auto自动推导变量的类型 auto并不代表某个实际的类型,只是一个类型声明的占位符 auto并不是万能的在任意场景下都能推导,使用auto声明的变量必须进行初始化,以让编译器推导出它的实际类型,…

苏东坡传-读书笔记十

不管怎么说,能使读者快乐的确是苏东坡作品的一个特点。苏东坡最快乐就是写作之时。一天,苏东坡对朋友说:“我一生之至乐在执笔为文之时,心中错综复杂之情思,我笔皆可畅达之。我自谓人生之乐,未有过于此者也…

红黑树模拟实现

概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡…

昇思25天学习打卡营第20天|RNN实现情感分类

数据准备 使用IMDB影评数据集,包含Positive和Negative两类。 数据下载 import os import shutil import requests import tempfile from tqdm import tqdm from typing import IO from pathlib import Path# 指定保存路径为 home_path/.mindspore_examples cache…

蚓链实践告诉你“企业确保达成数字化营销效果的方法”

在如今这个数字化盛行的时代,企业想在激烈的市场竞争里崭露头角,确保数字营销效果那可是至关重要!今天就来给大家聊聊实现这一目标的基本条件,来自蚓链数字化营销系统的广大用户体验总结。 一、精准的目标定位 企业一定要清楚地知…

第一作者讲述《生态系统架构:人工智能时代从业者的新思维》背后的故事:Episode One

当前,人工智能技术正不断渗透到各行各业,对企业和组织的系统和流程带来深刻的影响。生态系统架构可以帮助企业进行更好的规划和管理人工智能系统,使人工智能技术能够更好地为企业所用,从而实现企业的数字化转型和更好的商业表现。…

信号量——Linux并发之魂

欢迎来到 破晓的历程的 博客 引言 今天,我们继续学习Linux线程本分,在Linux条件变量中,我们对条件变量的做了详细的说明,今天我们要利用条件变量来引出我们的另一个话题——信号量内容的学习。 1.复习条件变量 在上一期博客中&…

HTML5实现我的音乐网站源码

文章目录 作者:[xcLeigh](https://blog.csdn.net/weixin_43151418) 1.设计来源1.1 界面效果1.2 轮播图界面1.3 音乐播放界面1.4 视频播放界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板,程序开发,在线开发,在线沟通 作…

DAY22-力扣刷题

1.被围绕的区域 方法一&#xff1a;深度优先搜索 class Solution {int n, m;public void solve(char[][] board) {n board.length;if (n 0) {return;}m board[0].length;for (int i 0; i < n; i) {dfs(board, i, 0);dfs(board, i, m - 1);}for (int i 1; i < m - 1…

项目方案:社会视频资源整合接入汇聚系统解决方案(九)-视频监控汇聚应用案例

目录 一、概述 1.1 应用背景 1.2 总体目标 1.3 设计原则 1.4 设计依据 1.5 术语解释 二、需求分析 2.1 政策分析 2.2 业务分析 2.3 系统需求 三、系统总体设计 3.1设计思路 3.2总体架构 3.3联网技术要求 四、视频整合及汇聚接入 4.1设计概述 4.2社会视频资源分…

5.opencv深浅拷贝

图像处理的复制操作 深浅拷贝 图像复制分成两种&#xff0c;第一种假复制&#xff0c;从原图片选择一部分图片拿出来观察&#xff0c;此时新生成的图片和原图实际上是同一张图片&#xff0c;即浅拷贝 将图片的一部分复制下来&#xff0c;放到新的内存中&#xff0c;即两张完全…

AI视频教程下载-使用ChatGPT成为全栈JavaScript开发者

学习使用Express JS和React JS进行全栈JavaScript开发 ChatGPT Express JS MongoDB React JS Tailwind 解锁全栈网页开发的世界&#xff0c;我们为初学者和中级学习者设计了全面的课程。在这段沉浸式的旅程中&#xff0c;你将深入前端和后端开发的基本概念&#xff0c;为自…

【DataSophon】DataSophon1.2.1 ranger usersync整合

目录 一、简介 二、实现步骤 2.1 ranger-usersync包下载编译 2.2 构建压缩包 2.3 编辑元数据文件 2.4 修改源码 三、重新安装 一、简介 如下是DDP1.2.1默认有的rangerAdmin&#xff0c; 我们需要将rangerusersync整合进来 ,实现将Linux机器上的用户和组信息同步到Ranger…

【Linux】线程(轻量级进程)

目录 一、线程概念 二、线程特性 2.1 进程更加轻量化 2.2 线程的优点 2.3 线程的缺点 2.4 线程的异常 2.5 线程用途 三、进程和线程 四、线程控制 4.1 包含线程的编译链接 4.2 创建线程 4.3 获得线程自身的ID 4.4 线程终止 4.5 线程等待 4.6 线程分离 4.6 线程…

Java数据结构9-排序

1. 排序的概念及引用 1.1 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录…

【Java】垃圾回收学习笔记(一):Root Search 根可达算法+垃圾回收的起点

文章目录 1. 引用计数法优点缺点 2. 可达性分析 Root Search2.1 那些对象是GC Roots2.2 引用的分类2.3 回收方法区 3. 实现细节3.1 GC的起点&#xff1a;节点枚举OopMap&#xff1a;帮助高效的根节点枚举 3.2 何时开始GC&#xff1a;安全点与安全区域如何选取安全点如何让程序进…