在物联网或类似领域,嵌入式设备需要与集中化的数据中心进行数据通信,数据中心还需要与第三方系统进行信息交换,这就形成了以“设备--数据中心--第三方系统”为基础结构的应用系统。
在该应用系统中,数据中心被拆分为“数据API”和“数据库”两个部分,数据API负责与设备、第三方系统进行交互。
在该数据 API 的设计中,需要注意设备数量极大、单设备性能不高的特点,尽可能的使数据 API 接口具备简单、高可靠、高可扩展的特点。
对比现有常见的 API 设计方式(WebService、RPC 和 REST 等),采用 REST 设计方式,可以充分利用 HTTP 协议的动词和状态码描述复杂的业务逻辑,利用 HTTP 无状态的特点构建可平行扩展的应用系统。同样重要的是,任何支持 HTTP 协议的编程语言都可以用于 REST 开发,这使得嵌入式设备上的 REST API 接口客户端更易实现。综上,采用 REST 方式设计该数据 API 接口。
REST(Representational State Transfer,表述性状态转移)是一种分布式应用架构风格。Web 的架构风格就是 REST,而 HTTP 1.1 规范也是基于 REST 架构风格的指导原理来设计的。
互联网应用往往有如下特征:可伸缩性要求难以预测和控制;安全性要求难以预测和控制;追求最大限度的松耦合;追求最大限度的简单性。随着企业 IT 建设的互联网化变革,无论是企业内部还是外部的数据 API 接口都渐渐呈现出上述特征。
REST 架构风格在实现上采用了 ROA(Resource-Oriented Architecture,面向资源的架构)架构,通过一个简单的、文档处理接口,来暴露其内部的数据,这种接口是统一的。REST 意味着,方法信息都在 HTTP 方法里,ROA 意味着,作用域信息都在 URI 里。
REST 架构风格中三个重要实体是:资源、HTTP、超媒体。REST 架构风格中四个主要特征是:可寻址性、无状态性、连通性、统一接口。
几乎所有东西都可以被建模为资源,然后通过网络来访问或操作。URI(Uniform Resource Identifier,统一资源标识符)唯一标识了一个资源,同时使得资源在 Web 上是可寻址的,也能够使用一种类似 HTTP 的应用协议来操作。URI 既是资源的名称,也是资源的地址。尽量把更多信息放在 URI 里,放在请求元数据里的信息越少越好。URI 一般以 HTTP URL 的形式呈现。
URI 和资源之间的关系是多对一的。一个 URI 仅仅标识一个资源,但是一个资源可以有多于一个 URI。尽管多个 URI 能够标识同一个资源,但是 Web 无法提供任何方式来计算两个不同的 URI 是否实际上指向同一个资源。
HTTP 是无状态的,这意味着每个 HTTP 请求都是完全独立的。当客户端发出一个 HTTP 请求时,请求里包含服务器实现该请求所需得全部信息,服务器不依赖任何之前请求提供的信息。
改变无状态型,最常用方法是利用 HTTP 会话:当一个用户首次访问网站时,得到一个唯一的字符串,用以标识用户在该网站上的会话;该字符串可以保存在 cookie 里,也可以放在给该用户的所有 URI 里。
REST 式架构要求把状态保存在客户端,并且在发给服务器的每个请求中都包含这些状态(加入需要的话)。服务器可以通过向客户端发送有状态的 URIs 为客户端提供进入新状态的机会,但服务器并不保存任何状态。
HTTP 数据中分为 HEAD(报头)和 BODY(主体)两个部分,HTTP 在传输数据时,主要关心 HEAD 部分,而不关心 BODY 的具体内容。HTTP 协议支持多种请求动词,主要有 GET、PUT、POST、DELETE、HEAD,每个动词表示特定的含义。HTTP 协议支持多种响应代码:官方的 HTTP 响应代码有41个,而常用的大约有10个左右。
HTTP 通过请求动词对资源进行操作:
HTTP PUT 和 POST 都可以用于创建资源,其区别是:假如是客户端负责决定新资源采用什么 URI,那就用 PUT;假如是服务器负责新资源采用什么 URI,那就用 POST。使用 POST 方法创建资源时,客户端不必知道新资源的确切 URI,仅需知道需要新建资源的父资源即可。服务器对 POST 请求的响应,通常返回 HTTP 状态码201(Created),并在 HEAD 的 Location 字段中包含新建从属资源的 URI。
“将超媒体作为应用状态的引擎(Hypermedia As The Engine Of Application State,HATEOAS)”,由 Roy Fielding 提出,用来描述 REST 架构风格的核心原则。
超媒体系统的特征是:根据(与应用协议参与者交换的)资源表述中的链接进行转移。在消费者与服务的交互中,消费者向服务的入口点提交了一个初始请求。服务处理该请求并用一个带链接的资源表述进行响应。消费者选择其中一个链接,以便迁移到交互的下一个步骤。这样的交互过程进行几轮之后,消费者就更接近其目标了,也就是分布式应用的状态发生了变化。在每一次交互中,服务和消费者交换的都是资源状态的表述,而不是应用的状态。被转移的标书中包括反映了应用状态的链接。但应用状态并不显式的记录在消费者收到的表述中,而是由消费者根据所有资源的状态(很可能分布于消费者目前正在与之交互的很多个服务中)推断出来。
使用 REST 方式设计数据 API,并将数据 API 关联为完整的业务流程。
常用于构建 Web 服务的架构有:REST 架构和 RPC 架构。很多 Web 服务在 HTTP 之上使用 SOAP,基本上每个采用 SOAP 的 Web 服务都属于 RPC 式架构。
所有 Web 服务都使用 HTTP 协议。REST 式 Web 服务,在 HTTP 方法里寻找方法信息,在 URI 里寻找作用域信息;而 RPC 式 Web 服务则往往忽略 HTTP 方法,在 URI、HTTP 报头或主体里寻找方法信息与作用域信息。
所有 Web 服务都使用 URI。REST 式面向资源的服务为客户端可能操作的每一则数据暴露一个 URI。REST-RPC 混合服务,为客户端可能进行的每一个操作暴露一个 URI。RPC 式服务,为每个处理远程调用的进程暴露一个 URI,一般来说这样的 URI 只有一个,即服务点。
许多只读的 Web 服务,尽管它们起初也许是按 RPC 风格设计的,但都可称得上是完全 REST 式和面向资源的。但是,如果该服务允许客户端修改数据的话,就会出现客户端所使用的 HTTP 方法与真正的方法信息不一致的情况——这样它就不具备 REST 式服务的特征了。这种架构方式常称为 REST-RPC 混合架构。
针对上述物联网业务场景,设计数据 API 接口。
接口说明:第三方系统获取数据中心中注册的所有设备的清单。
HTTP URL:http://example.com/device/
HTTP 请求方法:GET
HTTP 响应格式:JSON 格式
HTTP 响应样例:
{ "devices": [ { "mac": "7831C1C7FE5E", "name": "D1", "type": "TV" }, { "mac": "7831C1C7FE5F", "name": "D2", "type": "PHONE" }, { "mac": "7831C1C7FE6E", "name": "D3", "type": "PC" } ] }
接口说明:设备向数据中心注册新的设备信息。通过接口返回的 HTTP 状态码确定设备注册是否成功。
HTTP URL:http://example.com/device/{mac_address}/
HTTP 请求方法:PUT
HTTP 请求参数:mac_address - 设备的 MAC 地址(大写无冒号,例如:7831C1C7FE5E)
接口说明:设备向数据中心发送心跳信息,说明设备的在线状态。通过接口返回的 HTTP 状态码确定设备心跳是否记录成功。数据中心收到设备的 PUT 请求后,补充当前时间信息,将这些信息记录在数据库中。
HTTP URL:http://example.com/device/{mac_address}/heart/
HTTP 请求方法:PUT
HTTP 请求参数:mac_address - 设备的 MAC 地址(大写无冒号,例如:7831C1C7FE5E)
接口说明:第三方系统通过数据中心获取某设备的状态信息。返回 JSON 中的 htime 是指设备最后发回心跳信息的时间。
HTTP URL:http://example.com/device/{mac_address}/status/
HTTP 请求方法:GET
HTTP 请求参数:mac_address - 设备的 MAC 地址(大写无冒号,例如:7831C1C7FE5E)
HTTP 响应格式:JSON 格式
HTTP 响应样例:
{ "mac": "7831C1C7FE5E", "name": "D1", "type": "TV", "htime": "20141209-123433" }
接口说明:设备向数据中心上报性能数据,说明设备的运行状态。通过接口返回的 HTTP 状态码确定设备性能数据是否记录成功。
HTTP URL:http://example.com/device/{mac_address}/performance/{time_stamp}/
HTTP 请求方法:PUT
HTTP 请求参数:mac_address - 设备的 MAC 地址(大写无冒号,例如:7831C1C7FE5E)
time_stamp - 每十五分钟一个时间戳(YYYYMMDD-HH24MI,例如:20141209-2015)
HTTP 请求格式:JSON 格式
HTTP 请求样例:
{ "cpu": 56.34, "memory": 27.12 }
HTTP URL:http://example.com/device/{mac_address}/performance/{time_stamp}/
HTTP 请求方法:GET
HTTP 请求参数:mac_address - 设备的 MAC 地址(大写无冒号,例如:7831C1C7FE5E)
time_stamp - 每十五分钟一个时间戳(YYYYMMDD-HH24MI,例如:20141209-2015)
HTTP 响应格式:JSON 格式
HTTP 响应样例:
{ "cpu": 56.34, "memory": 27.12 }
《Architectural Styles and the Design of Network-based Software Architectures》,Roy Fielding
《REST In Practice》,Jim Webber/Savas Parastatidis/Ian Robinson,Oreilly
《RESTful Web Services》,Leonard Richardson/Sam Ruby,Oreilly