前段时间我大发雷霆,因为有人曲解了REST在微服务中的作用,而且没能正确使用它。有人认为无法基于HTTP进行异步交互,所以基于HTTP的单体系统无法被分解成微服务。大多数人认为HTTP就是REST,这是件让人感到悲哀的事情。在我们的行业里,这些人都是很有经验的,本该知道这两者其实是不一样的。如果你也分不清它们之间的区别,那么请先看看Rest Cookbook或者Roy博士的文章。

好吧,似乎有点跑题了,让我们回到之前说的问题上:我之所以大发雷霆,是希望把大家引导到正确的方向上,同时给大家提供一些建议。

REST和HTTP

首先,并不是说构建微服务一定要基于HTTP。关于这个,可以看看InfoQ上早前发表的一些相关文章,或者回顾过去7年我们在WildFly/EAP及其它项目上所做的事情。

HTTP不是唯一的选择,它有它的不足,不仅仅因为它是基于文本的协议,在性能上它也比不过更成熟的IIOP。这个问题在Narayana项目中就暴露出来了,就算是二进制版本的HTTP/2也不行。

并不是说HTTP在性能方面存在不足才劝你要抛弃它的,我们还有其它的选择。传统的消息中间件,如A-MQ,它支持很多种模式,包括代理和非代理模式,还支持AMQP和MQTT协议,让异构系统之间的交互变得更通畅。

当然,我并不是说一定不要使用HTTP构建微服务。但是当我们跟很多分布式系统打交道的时候,不得不考虑其它很多方面的问题,比如可靠性,性能,耦合度等等。不是非用HTTP不可,不过JMS也一样。我知道,基于HTTP构建的的服务容易测试,只需要一个浏览器。不过也可以考虑其它的工具,比如Arquillian。

异步调用

现在我们来谈谈异步HTTP。有些人说HTTP可以实现异步调用,这个有可能吗?当然有可能,下面我会给出一些参考。

首先,我们拿一些知名的项目来作为例子,比如Vert.X和Undertow,它们都基于HTTP实现异步消息交互。这两个都是很受欢迎的项目,很多人使用它们构建了很多大型应用。

其次,你可以不相信我所说的,但是你可以去翻看InfoQ上关于这个主题的文章。这样的文章有很多,甚至可以追溯到10年前。如果要我推荐关于这个主题的书,我会推荐我的一个老朋友也是前同事Jim Webber,或者另外一个老朋友也是现任同事Bill Burke的书。

在使用HTTP的时候,响应码对我们来说很重要。对于200,403,404这样的响应码我们已经很熟悉了,但HTTP还有一些东西使得实现异步交互变为可能,比如202。在HTTP协议规范里是这样描述202的:

请求已被接受,但是还没有处理完毕。  请求最终有可能不会被处理,因为系统可能不允许处理该请求  。对于这种情况,没办法通过异步操作来重新发送一个状态码。202响应不保证处理结果,  它只是允许服务端接收请求,而不需要让客户端一直等待处理结果  。它的响应里应该包括一些内容,比如当前请求的处理状态,或者让客户端知道去哪里可以得到处理状态,或者告诉客户端请求处理完毕的大致时间。

很显然,我加亮的地方指的就是“异步处理”。这个响应码肯定不是大家经常看到的,而且就算用到了,也因为被浏览器隐藏,所以仍然看不到。重点是,HTTP支持异步调用。作为开发者,我们也一定能利用这点。

如果你在考虑使用标准框架来处理异步HTTP,你大概会想到JAX-RS。网上有很多相关的资料,Bill Burke的那本书也不错。他甚至写了JAX-RS2.0,值得一看。Bill所在的标准制定小组在他们新版本协议规范里还特意增加了支持回调的异步客户端API。而且我们不要忘了Bill早在2009年作的关于早期协议版本的演示。

它是真的异步吗?

如果你读到这里,应该很清楚,基于HTTP的异步处理完全是有可能的。不过我还是想指出它的一些瑕疵,就像有些文章说的那样。

当人们说到异步交互,一般指的是以下两种类型。一种是请求被同步发送到服务端,服务端返回一个确认响应,告诉客户端请求最终会被处理并返回结果。这种方式可以提高并发性。另外一种是"触发然后忘记"模式,服务端不会返回任何确认给客户端。

所幸的是,当大多数人提到第二种方式时,其实他们心里想的是第一种,因为他们直接把确认响应给忽略掉了。这两者的区别其实很关键,在真实的异步系统中,不可能只通过时间的长短来判断一个端点到底是崩溃了还只是响应慢。这个在做系统架构决策的时候很重要。

权衡利弊

Fischer,Lynch和Patterson这三个人在1985年发表了一篇论文,获得Dijkstra最具影响力论文奖。他们在论文中证明了FLP理论,即无法通过时间长短来判断一个端点是否已崩溃。大多数人认为这在同步系统中是有可能的,但是在异步系统中是不可能的,就算整个系统中只有一个糟糕的处理器。

你也许会问为什么这个如此重要。很显然,如果你处在一个真实的异步交互场景中,需要知道哪些调用可以直接得到结果,而哪些不会。这不是在纸上谈兵,论文里已经说得很清楚了,所以在开发的时候要小心这方面的问题。

因此,所有关于事务的协议,包括Narayama里的那些,都应该是同步的。

还有个事情需要注意,有些人把Brewer的CAP理论同FLP混为一谈。尽管CAP和FLP都跟分布式系统的行为有关,但它们之间有一些明显的区别:

CAP认为在异步网络里无法实现同时满足以下三点的支持读写的存储系统。

  • 可用性——每个请求最终都会收到响应

  • 一致性——服务端为每个请求返回正确的响应

  • 分区容错——允许消息丢失

从某种程度上说,CAP听起来有点像FLP,但其实不是。如果你真的感兴趣,可以看看Ken Birman的论文。

FLP允许网络里有节点崩溃,但不允许有消息丢失。

上面的信息已经超出了一个开发者本该知道的范围,但多知道一些关于分布式系统的陷阱总是有好处的。还有就是,我们一定要小心,有时候人们说到CAP或者FLP,并不代表他们真的理解背后的原理。而事实是,CAP经常被人误解和滥用。


欢迎关注“互联网架构师”,我们分享最有价值的互联网技术干货文章,助力您成为有思想的全栈架构师,我们只聊互联网、只聊架构,不聊其他!打造最有价值的架构师圈子和社区。

本公众号覆盖中国主要首席架构师、高级架构师、CTO、技术总监、技术负责人等人 群。分享最有价值的架构思想和内容。打造中国互联网圈最有价值的架构师圈子。

  • 长按下方的二维码可以快速关注我们

  • 如想加群讨论学习,请点击右下角的“加群学习”菜单入群


REST和微服务——用异步交互分解单体系统相关推荐

  1. 走出微服务误区:避免从单体到分布式单体

    最近社区频繁出现的对微服务的各种质疑和反思的声音,甚至放弃微服务回归单体.本文从"分布式单体"问题出发,介绍通过引入非侵入式方案和引入Event/EDA 来走出微服务实践误区:从单 ...

  2. 【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问?

    点击上方"蓝字", 右上角选择"设为星标" 周一到周五早11点30,精品文章准时送上! 本文来自石杉的架构笔记 目录: 一.问题起源 二.Eureka Serv ...

  3. SpringCloud微服务注册中心如何承载大型系统的千万级访问?源码及原理分析

    2019独角兽企业重金招聘Python工程师标准>>> 问题起源     Spring Cloud架构体系中,Eureka是一个至关重要的组件,它扮演着微服务注册中心的角色,所有的服 ...

  4. 微服务注册中心如何承载大型系统的千万级访问?

    本文来源:石杉的架构笔记(shishan100) 目录: 一.问题起源 二.Eureka Server设计精妙的注册表存储结构 三.Eureka Server端优秀的多级缓存机制 四.总结 一.问题起 ...

  5. 【双11狂欢背后】微服务注册中心如何承载大型系统的千万级访问?

    一.问题起源 Spring Cloud架构体系中,Eureka是一个至关重要的组件,它扮演着微服务注册中心的角色,所有的服务注册与服务发现,都是依赖Eureka的. 不少初学Spring Cloud的 ...

  6. 基于spring boot的邮件微服务消息中间件设计与实现 毕业论文+系统功能图v1.0.vsdx+项目源码

    下载地址:https://download.csdn.net/download/m0_63680064/36065411 项目介绍: 基于spring boot的邮件微服务消息中间件设计与实现 毕业论 ...

  7. 微服务架构 接口交互问题_架构师的故事:设计微服务架构

    架构师在软件项目中的作用是提供待解决问题的工作模型.架构师的工作是提供脚手架,开发人员将根据这些脚手架构建他们的代码,使应用程序所有部件都组合在一起. 在构建微服务架构时,项目的架构师主要关注以下3个 ...

  8. 微服务的异步通信技术RabbitMQ

    文章目录 前言 1.WorkQueue(工作队列) 消息预取机制 2.Publish&Subscribe(发布-订阅) 1.Fanout(广播) 2.DirectExchange(路由) 3. ...

  9. 基于微服务架构,改造企业核心系统之实践

    2019独角兽企业重金招聘Python工程师标准>>> 1. 背景与挑战 随着公司国际化战略的推行以及本土业务的高速发展,后台支撑系统已经不堪重负.在吞吐量.稳定性以及可扩展性上都无 ...

  10. 微服务架构带来的分布式单体,更好还是更坏,一念之间

    前言 微服务架构其实是为了服务可以独立的开发.独立的部署,快速迭代,并且技术多样性. 然而我们经常在开发微服务的时候没有弄清楚微服务的边界,导致了一个更大的坑,由单体架构拆分成了微服务单体架构,带来了 ...

最新文章

  1. 常用的CSS命名规则
  2. html中的li排成一行怎么写,html怎么实现li元素有点并分列
  3. 9号团队-团队任务4:每日立会(2018-11-26,2018-11-27)
  4. 多层陶瓷电容器用处_典型陶瓷电容的用途和作用
  5. avaya http文件服务器,avaya 通讯服务器配置
  6. 洛谷P1396 营救 题解
  7. LOD优化策略-通篇
  8. pycharm matplotlib 图片显示
  9. 微软商业智能BI知识整合篇-五大工具产品系列文章
  10. mysql utf 8bm4 没用_不要在 MySQL 中使用“utf8”,請使用“utf8mb4”
  11. 程序员的进阶课-架构师之路(16)-散列表(哈希表)
  12. TMD 之后,再无 BAT? | 畅言
  13. div滚动条怎么设置_【20201123】做个用户管理系统(7)——个人资料修改页面、用户头像设置页面的模板的制作...
  14. postgres数据库入门, python 操作postgres
  15. 比较linux的桌面环境的使用和异同?_深度UI + Ubuntu系统,堪称最强最美Linux发行版!你敢升级吗?...
  16. C语言--(四)常用运算符
  17. TMS320C6678入手准备
  18. Linux 利用date命令进行时间戳转换
  19. 元器件及测量基础实验
  20. vscode 编辑特效 文字爆炸效果插件

热门文章

  1. Nginx 设置文件缓存时间
  2. internet缓存Temp中的tmp文件
  3. 「leetcode」56. 合并区间【贪心算法】详细图解!
  4. hdu 1864 最大报销额 模型为简单的01背包
  5. hdu 4339 Query 线段树 多校联合赛(四) 第九题
  6. inDesign 教程,如何调整布局元素的大小?
  7. 在 Mac 上拷贝(复制)、粘贴的方法
  8. 如何在旅途中提升 MacBook 电池电量?
  9. 如何在 Mac 上的 Pages 文稿中格式化文本栏?
  10. PhotoMill X for Mac(图片批处理工具)