请求--响应类的API的典型作法是,经过基于HTTP的Web服务器暴露一个/套接口。API定义一些端点,客户端发送数据的请求到这些端点,Web服务器处理这些请求,而后返回响应。响应的格式一般是JSON或XML。浏览器
在这种类型的Web API里,比较流行的是这三种:REST,RPC和GraphQL。缓存
REST全称是Representational State Transfer 表述性状态传递。REST多是如今最流行的一种Web API。安全
REST的核心就是资源,一个资源就是能够被标识的实体,它有名称和地址。服务器
REST API就是把数据以资源的形式暴露出来,并使用标准的HTTP方法来表明建立、读取、更新和删除资源等事务。数据结构
REST API有一些规则和约束,这里我就简单的写一下(以前的文章有详细描述):工具
资源都是URL的一部分,例如/persons性能
针对每一个资源一般都会有两个URL被实现:“/persons”表示资源的集合,“/person/321”表示特定的一个资源3d
在资源里,使用名词而不是动词,例如 /getUserInfo/123 这就不对了,应该是 /users/123代理
HTTP方法代表了要执行的动做,不一样的HTTP方法做用于同一个URL上可实现不一样的功能:blog
建立 -- POST
读取 -- GET
总体更新 -- PUT
局部更新 -- PATCH
删除 -- DELETE
服务器会返回标准的HTTP状态码,来表示请求成功或者失败,以及缘由。一般2xx表示成功,3xx表示资源被移动了,4xx表示客户端引发的错误,5xx表示服务器端引发的错误。
若是两个资源有主从关系,那么子资源最好不采用顶级资源的URL,而是采用主资源的子资源URL地址。例如Province和City就是主从关系,那么City资源的URL应该是:/provinces/{provinceId}/cities,/provinces/{provinceId}/cities/{cityId}
非CRUD操做
API不免会有一个非CRUD的操做,例如“存档”这个操做。这时候咱们能够采起如下几种办法:
把这个动做做为资源的一个字段。例如把“存档”做为输入参数传递到API
做为子资源。例如 /repos/{repoId}/issues/{issueId}/archive
直接使用动词。实在不行了,就用动词吧,例如 /search/params?......
Remote Procedure Call。RPC是一种比较简单的API,客户端直接会执行另外一个服务器上的代码。
REST是关于资源的,而RPC就是关于动做的。
在RPC里,客户端一般是把方法名和参数传递给服务器,而后服务器返回JSON或XML。
RPC的规则比较少:
端点要包含被执行操做的名字
使用合理的HTTP动词,GET用于读取,POST用于其它类型。
RPC适用于那种没法用CRUD封装的动做,或者其影响和资源无关的动做。
RPC不只限于HTTP,还有其它协议能够支持,例如Apache Thrift和gRPC。
GraphQL 是 API的查询语言。最近愈来愈火。它由Facebook于2012年开始开发,2015年被开源了。
GraphQL容许客户端定义须要获得的数据结构,服务器精确的返回所需的数据结构,例如:
与REST和RPC不一样,GraphQL API只须要一个端点;它也不须要使用不一样的HTTP动词,它只使用POST,你须要在JSON body里面指定是要执行查询仍是修改。
相对REST和RPC,GraphQL有下面几个优点:
节省了多重的请求往返,GraphQL能够一次把所需的关联数据所有查询出来。不会存在例如N+1这样的问题
避免了API版本问题。你能够随时添加字段和类型,不会影响现有的查询。能够标记弃用。经过Log能够追踪出哪些字段被谁使用,若是字段没人再去使用,就能够移除它了。
Payload比较小。REST和RPC的响应都包含客户端发送一些不须要的数据。而使用GraphQL的话,客户端获得的响应就是它所请求的那些东西,很少很多。
强类型。GraphQL是强类型的,开发时有类型检查能保证查询的正确性和合理性。
内省(Introspection)。像REST,就须要安装Swagger等工具来帮助浏览API。而GraphQL自己就具有可发现性。它还带有一个浏览器内的IDE用来浏览GraphQL API。下图就是Github的GraphQL API:
GraphQL的缺点就是它为服务器添加了许多复杂性,服务器须要额外的工做来处理这些复杂的查询。根据查询内容的不一样,性能也是一个变数.
针对CRUD类的API,使用REST
针对暴露不少动做的API,使用RPC
当你须要查询的灵活性以及维护的连续性时,使用GraphQL
针对用请求-响应式API,若是服务的数据常常变化,那么响应就可能没法保持新鲜了。开发者若是想与变化的数据保持同步,就只能对API进行polling操做了。
可是若是poll的频率较低,客户端仍有可能没法得到从上次poll到如今全部的数据事件。若是poll的频率较高,还特别浪费资源。
因此咱们须要实时的分享事件的数据,一般使用下面三种机制:WebHook,WebSocket,HTTP Streaming。
WebHook就是一个接收HTTP POST(或GET,PUT,DELETE)的URL。一个实现了WebHook的API提供商就是在当事件发生的时候会向这个配置好的URL发送一条信息。与请求-响应式不一样,使用WebHook,你能够实时接受到变化。
下面是Polling和Webhook的比较:
WebHook很是适合于从一个服务器向另一个服务器分享实时数据。
可是实现WebHook,也引入了新的复杂性:
失败和重试。为了保证WebHook被成功的传输,你须要构建一个能够再发生错误时进行重试操做的系统。
安全性。对于安全的调用REST API,如今的方案都比较成熟;而对于WebHook来讲,这方面依然在探索中前进。
防火墙。防火墙后运行的应用能够经过HTTP访问API,可是它们可能没法接收入站的流量。因此这是一个很大的问题。
噪声。一般每一个WebHook调用表明了一个事件,但当短期内发生了成千上万个事件的时候,再经过WebHook来传输,就可能会有噪音。
WebSocket这个协议,它经过一个TCP协议创建一个双向全双工的流式通讯。WebSocket一般用在客户端和服务器之间的通讯,也能够用在服务器之间的通讯。
ASP.NET Core SignalR就是优先使用该协议。
WebSocket支持全双工(服务器和客户端能够同时双向通讯),并且开销不高。常用的端口式80或443,这样就很容易穿过防火墙了。
WebSocket特别适合于快速的,现场的路i数据和长链接。
若是链接挂掉了,客户端会尝试从新初始化链接。可是WebSocket有一些扩展性的问题,由于若是在线的客户端太多,那么服务器端就须要维持这些客户端打开的链接。
使用请求-响应式API,客户端发送一个请求,服务器端返回一个响应,这个响应的长度是有限的。
而使用HTTP Streaming,服务器端能够在一个由客户端打开的长生存的链接里持续的推送新数据。
为了让数据经过一个可长时间存在的链接上进行传输,有两个方案:
首先可让服务器把Transfer-Encoding这个Header设为chunked。这表示客户端是按块接收数据的,块与块之间用换行符分割:“\r\n”。
另外一个选项是经过Server-Sent Events (SSE)来进行流数据。这个比较适合于浏览器内的客户端,由于这样它们就可使用标准的EventSource API了。(SignalR在没法使用WebSocket的时候就会使用SSE)
HTTP Streaming用起来好像很容易,可是有个问题,是关于缓存的。客户端和代理常常会有缓存的限制。由于只有达到某个阈值以后,它们才会把数据渲染给应用。
若是想要进行服务器间的实时事件通讯,能够选择WebHooks
若是须要浏览器和服务器间的双向实时通讯,能够选择WebSocket
若是须要使用简单的HTTP进行单向通讯,可使用HTTP Streaming