一、前因后果
在写后续文字之前,首先申明两点:1、无意于引起编程语言和架构设计之争;2、对网页开发和使用Java、Python的程序员没有鄙视链。本文仅仅从自身经历过的事情,来讨论RESTful。
我在金融软件开发领域工作多年,主要开发交易行情类和资讯类系统。经常遇到互联网领域,特别是做网页的同事,与此讨论关于系统架构的设计,是件令人头疼的事情。以行情发布系统为例,这系统不是像新浪财经,分钟级别刷出来都没有事,而是作为交易依据,手慢都要吃土的那种。比如说国债期货行情。
网络上也有很多大牛介绍如何使用RESTful架构微服务系统,于是乎WEB架构师动则鼓吹REST如何优秀,如何简单。不知如何通过评审,以WEB+json+AJAX来实现行情的推送。虽然耗费大量资金、人工和时间,可惜的是,即使换了几个团队折腾,我也未见过有成功案例。为了让后来者不再重蹈旧履,有必要审视RESTful的适用场景。
二、REST的由来
我不清楚言必提RESTful的人们,可曾认真研读过REST的论文并了解它的历史,网址见:https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm。2000年,Roy在他的博士论文中正式定义了REST。在回顾REST发展过程中,Roy说过:“在整个HTTP标准化过程中,让我去辨证Web的设计选择。我不得不从Web交互最抽象的标记深入到HTTP语法细节来详细解释其中一切。这个过程把我的模型打磨成一些列核心原则,特性以及约束。”换言之,REST是基于HTTP而提炼出来的架构风格。它的产生背景,决定了它的基因和WEB有无法割断的联系。
额外的一些补充信息,Roy回答的问题:http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
三、RESTful约束
1、统一接口。它是任何REST服务设计的基础,统一接口包含了资源定义和定位。这在任何场景下,都是有好处,就如普通话是国内交流的通用语言,英语是国际交流的通用语言,大家都要懂。Roy Fielding还强调REST API必须是HyperText驱动的。HyperText是通用协议,更容易被理解,因此有能力穿透各个服务层。比如防火墙,基本没有不支持HTTP协议的防火墙,却从未听说哪个品牌支持AMQP,更遑论私有协议。
2、C-S分离,分层系统。这个也容易理解,互联网系统多是C-S和分层系统,不符合这个特点的反而不多见。
3、无状态。这个约束就比较坑了,也是最难把握的约束,Roy认为,“每个客户端请求必须包含所有的服务理解该请求的信息,服务端不能利用任何已经被存储的上下文,会话信息也因此全部被保存在客户端”。无状态赋予系统可扩展性和幂等性等无与伦比的优势,但并非所有的场景都能简单地转换成无状态。
4、缓存、按需代码。这个也不难理解,缓存在任何系统都一样,静态文件更容易被缓存处理,对CDN支持也好。按需代码,在WEB中由javascript等脚本语言,在其他架构中,并没有特别约定。
四、无状态解析
如前述,RESTful系统,必须符合无状态约束,反言之,不符合无状态约束的系统不是RESTful。WEB系统是互联网世界最庞大也是最成功的系统,HTTP功不可没。每个WEB网站之间基本没有关联,可拓展性是天然的。
与此同时,在早期的WEB系统多以静态内容为主,比如文件,天然满足无状态的约束。而随着交互需求不断深入,动态内容的规模也迅速增长,比如社交。论坛时代,发个帖,可以去吃顿饭再回来看回复,还不一定有。
12306订票网站,中国人都知道,春运期间,出票基本秒光。按照REST约束,状态必须保存在客户端,那我们可以轻易修改,告诉12306,这票已经是我的了。这显然是不对,主要是为了说明,无状态的局限性。即使我们通过各种手段,弥补无状态这种场景所带来的收益,也可能赶不上付出的代价,甚至还附带着一堆漏洞。
五、HTTP的缺陷
RESTful基于HTTP,那么HTTP的局限性,它也同样具备。我们知道HTTP是建立在TCP上的,在完成数据传输后,即关闭连接,一次C-S对话结束。在互联网中,创建一次连接的代价是很高的,一次同城达到20毫秒也是很正常,而跨城70毫秒,跨洲际300毫秒。如果在浏览器中,由于人眼感知帧数24帧,在40毫秒左右;并且在3秒内,基本不会产生不耐烦情绪。
另外一方面,WEB不但会传输数据,同时还会传输界面描述文本,文本在传输量又比二进制等方式要大。在安全方面,如果遵循REST约束,将状态保存在客户端,不是由服务端控制和校验,那么是很难确保安全性的。所以,在支付领域,如支付宝和银行,都要在浏览器中,加上自己的安全插件。
综合考虑,这些缺陷导致HTTP协议在高频低延迟安全等领域,必须谨慎对待。HTTP的诸多优势,是他大范围应用的根本。但并不意味着他是放之四海而皆准的设计。
六、行情发布系统
回到最初行情发布系统的案例,作为交易重要参考系的行情,在延迟上的要求是很高的,有些资产类别,如股票,行情的发布量非常大。单一个深交所的Level2行情,在联网测试时要求10Mb的行情带宽。而市场上多数行情发布平台,是将多个行情点整合在一起后,再发布给终端客户,原始总量更大。
行情发布的时机是由服务端触发的,客户端并不知道何时需要刷新,如果频繁轮询的话,服务端基本是扛不住的,除非客户端的量很小。在此场景下,REST的架构所带来的简单可扩展优势,几乎不复存在。