草庐IT

读书笔记丨远程服务调用和RESTful,如何分析和抉择?

华为云开发者社区 2024-01-02 原文
摘要:相信未来REST规范将会变得更加流行和普及。

本文分享自华为云社区《云原生时代,远程服务调用和RESTful,如何分析和抉择?》,作者:breakDawn 。

随着云原生的概念越来越火,服务的架构应该如何发展和演进,成为很多程序员关心的话题。大名鼎鼎的《深入理解java虚拟机》一书作者于21年推出了新作《凤凰架构》,从这本书中可以看到当前时下很多最新的技术或者理念。

本博文将沉淀发布这本书的学习笔记和思考。 如果希望了解更加详细的内容,欢迎购买该书继续详细学习。

访问远程服务

1 远程服务调用

这一个章节主要讲解rpc的设计理念和发展历史。
先是讲解了IPC(进程间通信)所需要的各个必要因素
接着解释RPC 是IPC的一种特例(这是最初科学家们的想法)
但PRC存在很多可靠性的问题,并不能直接等同IPC的扩展。

接着提出了RPC的三个基本问题:

  1. 如何表示数据
    即序列化协议, 有grpc的proto-buffer、json、xml、java-rmi基于java自带序列化之列的
  2. 如何传递数据
    基于什么网络协议传输
    java-rmi的远程协议
    JSON-RPC协议
    SOAP协议(web service 简单对下访问)
  3. 如何表示方法
    如何定义方法,如何在不同语言、不同系统环境中保证 方法签名唯一。
    需要对接口描述定义语言有一个选型

再后面讲解了rpc的发展历史
CORBA的使用过于复杂,被抛弃
SOAP使用xml很简单,但是性能奇差
可以看出RPC想同时满足简单、普适、高性能是很难的
于是得出一个结论:

不存在完美的RPC框架

最近几年的RPC框架更倾向于往高层次、插件化发展。
即不再独立解决RPC的所有问题,而是提供一些扩展点由用户自己选择(比如dubbo)
可以任意切换json或者fastjson等序列化方式
可以切换传输协议等。

2 REST

rest并不是一种远程调用协议, 他只能说是一种风格。
REST的传输效率提升潜力有限,但是可以简化调用。

2.1 REST核心概念(基于HTTP超文本传输协议)

  • 资源
    资源指你希望获取或者修改的东西、信息本身,他的表现形式可以不同,但是里子是相同的
  • 表征
    就是表现资源的形式,用html还是pdf来返回
  • 状态
    指的是服务端对某次会话是否持有状态。
    例如读下一篇文章时,当前文章id由服务端存储还是浏览器存储,这就是有状态和无状态的区别。
  • 转移
    就是服务端提供的行为逻辑, 通常叫做 资源的转移
  • 统一接口
    就是HTTP协议里提供的GET\HEAD\POST\PUT\DELETE\TRACE\OPTIONS这七种操作,通过这些操作触发转移
  • 超文本驱动
    浏览器的行为经常是通过服务端返回的url或者各种信息触发了驱动行为
  • 自描述消息
    为了方便客户端识别表征,返回类似于Content-Type等内容,方便用何种字符集处理

2.2 REST核心设计原则

  1. 客户端与服务端分离
    服务端不处理渲染, 由客户端来处理
  2. 无状态
    尽可能希望服务端不要存储rest会话状态,达到分布式的高价值回报。
    但是不太可能特别是客户端持有会话数量级很大的情况下,所以仍旧会持有一定状态
  3. 可缓存
    服务端的应答中要直接或者间接告知客户端是否可以缓存,缓存多久
  4. 分层系统
    客户端不需要知道是否真的连接到了最终的服务器
    代表是CDN内容分发网络
  5. 统一接口
    面向资源编程
    系统设计时聚焦在资源而不是行为上
    例如面向行为时, 登录就是login接口,注销就是logout接口
    而面向资源时,登录就是PUT Session, 注销就是DELETE Session
  6. 按需代码
    客户端的代码可以有一部分让服务端发回进行装载。

2.3 REST的好处

  • 降低服务接口的学习成本
  • 资源天然具有集合与层次接口
    这样很多资源可以很容易组合在一起并让使用者想到接口url是什么
    例如获取 用户 icyfenix的购物车中的第2本书,这个是有层次的,那么接口就是GET /user/icyfenix/cart/2
  • REST绑定于HTTP协议,HTTP又是大家非常熟悉的

2.4 RMM(Richardson提出的restful成熟度模型)

第0级:完全不rest

提供的api定义里总是包含了各种动作,例如
/queryXXX
/applyXXX
类似于RPC的行为接口
坏处是一旦要提供其他对XXX的操作,必须重新编写接口,无法对XXX的查询能力进行复用!

第1级:开始引入资源的概念

api的endpoint定义应该围绕名词+资源id而不是动词来定义。
POST /doctors/mjones 获取医生的档期
POST /schedules/{id} 触发对这个id的调度

第2级: 引入统一接口,映射到HTTP方法上

上面的method都是POST,实际上可以把HTTP方法的method、返回码都给利用上

  • 对一个资源的增加用POST,删除用DELETE,更新用PUT
  • 依赖HTTP的返回码定义资源可能的异常情况。例如201代表创建成功,409代表冲突(被人抢先预约)
  • 利用HTTP自带的认证和授权信息。

第3级:超文本控制,转移行为通过响应控制

第2级里, 所有接口的定义仍然需要使用者自己查询文档来记忆和应用
实际上应该只需要一个操作起始入口, 例如获取医生的档期接口
这个接口要返回的body里,已经告知了对应资源的名称,例如档期资源的key就叫做schedules
那么就能马上知道下一个接口查询用schedules了!
这样代码里可以做好适配,当你要把档期的key名做修改时,客户端代码根本不用变动!

2.2.4 REST的不足和争议

1.restful面向资源编程只适合做CRUD,不适合过于复杂的业务逻辑

  • 面向过程编程,以算法和处理过程为中心,这符合计算机世界中主流的交互方式
  • 面向对象编程,将数据和对象行为统一起来,因为这符合现实世界的主流交互方式
  • 面向资源编程,数据作为主体,行为看成统一接口,为了符合网络世界的主流交互方式

2.rest不利于事务支持
作者不同意这个观点, 认为不会有阻碍,取决于系统的事务设计

3.rest没有传输可靠性支持
虽然确实没有类似于重发等机制的保证,但rest接口一般尽可能要求幂等性,来做到应用代码做重发时可以不用担心重复的问题

4.缺少对资源做部分或者批量处理的能力
rest语义里不能涵盖这种情况,得定义特殊的接口或者参数,那么低3级里面就不能涵盖了。

相关思考

基于REST的规范,调用者可以非常快速地理解自己需要的接口内容是什么样的,例如华为云当前的很多云服务公开接口都会基于REST理念进行开放, 并且各云服务的开放接口都会集成到API Explorer华为云SDK中心供开发者直接调用,这些平台提供了丰富的接口文档和示例代码,帮助开发者更快地上手和使用 REST 接口。

相信未来REST 规范将会变得更加流行和普及。随着云计算和大数据技术的不断发展,REST 接口将会被广泛应用于各种领域,例如医疗、金融、电商等。REST 接口的开放性、可扩展性和易用性,将会为开发者带来更加高效、便捷和可靠的开发体验。

 

点击关注,第一时间了解华为云新鲜技术~

有关读书笔记丨远程服务调用和RESTful,如何分析和抉择?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  4. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  6. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  7. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  8. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  9. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐