精读《REST,GraphQL,Webhooks gRPC 如何选型》
1 引言
每当项目进入联调阶段,或者提前约定接口时,前后端就会聚在一起热火朝天的讨论起来。可能 99% 的场景都在约定 Http 接口,讨论 URL 是什么,入参是什么,出参是什么。
有的团队前后端接口约定更加高效,后端会拿出接口定义代码,前端会转换成(或自动转成)Typescript 定义文件。
但这些工作都针对于 Http 接口,今天通过 when-to-use-what-rest-graphql-webhooks-grpc 一文,抛开联调时千遍一律的 Http 接口,一起看看接口还可以怎么约定,分别适用于哪些场景,你现在处于哪个场景。
2 概述
本文主要讲了四种接口设计方案,分别是:REST、gRPC、GraphQL、Webhooks,下面分别介绍一下。
REST
REST 也许是最通用,也是最常用的接口设计方案,它是 无状态的,以资源为核心,针对如何操作资源定义了一系列 URL 约定,而操作类型通过 GET
POST
PUT
DELETE
等 HTTP Methods 表示。
REST 基于原生 HTTP 接口,因此改造成本很小,而且其无状态的特性,降低了前后端耦合程度,利于快速迭代。
随着未来发展,REST 可能更适合提供微服务 API。
使用举例:
curl -v -X GET https://api.sandbox.paypal.com/v1/activities/activities?start_time=2012-01-01T00:00:01.000Z&end_time=2014-10-01T23:59:59.999Z&page_size=10 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token"
gRPC
gRPC 是对 RPC 的一个新尝试,最大特点是使用 protobufs 语言格式化数据。
RPC 主要用来做服务器之间的方法调用,影响其性能最重要因素就是 序列化/反序列化 效率。RPC 的目的是打造一个高效率、低消耗的服务调用方式,因此比较适合 IOT 等对资源、带宽、性能敏感的场景。而 gRPC 利用 protobufs 进一步提高了序列化速度,降低了数据包大小。
使用举例:
gRPC 主要用于服务之间传输,这里拿 Nodejs 举例:
1.定义接口。由于 gRPC 使用 protobufs,所以接口定义文件就是 helloword.proto
:
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
这里定义了服务 Greeter
,拥有两个方法: SayHello
与 SayHelloAgain
,通过 message
关键字定义了入参与出参的结构。
事实上利用 protobufs,传输数据时仅传送很少的内容,作为代价,双方都要知道接口定义规则才能序列化/反序列化。
2.定义服务器:
function sayHello(call, callback) {
callback(null, { message: "Hello " + call.request.name });
}
function sayHelloAgain(call, callback) {
callback(null, { message: "Hello again, " + call.request.name });
}
function main() {
var server = new grpc.Server();
server.addProtoService(hello_proto.Greeter.service, {
sayHello: sayHello,
sayHelloAgain: sayHelloAgain
});
server.bind("0.0.0.0:50051", grpc.ServerCredentials.createInsecure());
server.start();
}
我们在 50051
端口支持了 gRPC 服务,并注册了服务 Greeter
,并对 sayHello
sayHelloAgain
方法做了一些业务处理,并返回给调用方一些数据。
3.定义客户端:
function main() {
var client = new hello_proto.Greeter(
"localhost:50051",
grpc.credentials.createInsecure()
);
client.sayHello({ name: "you" }, function(err, response) {
console.log("Greeting:", response.message);
});
client.sayHelloAgain({ name: "you" }, function(err, response) {
console.log("Greeting:", response.message);
});
}
可以看到,客户端和服务端同时需要拿到 proto 结构,客户端数据发送也要依赖 proto 包提供的方法,框架会内置做掉序列化/反序列化的工作。
也有一些额外手段将 gRPC 转换为 http 服务,让网页端也享受到其高效、低耗的好处。但是不要忘了,RPC 最常用的场景是 IOT 等硬件领域,网页场景也许不会在乎节省几 KB 的流量。
GraphQL
GraphQL 不是 REST 的替代品,而是另一种交互形式:前端决定后端的返回结果。
GraphQL 带来的最大好处是精简请求响应内容,不会出现冗余字段,前端可以决定后端返回什么数据。但要注意的是,前端的决定权取决于后端支持什么数据,因此 GraphQL 更像是精简了返回值的 REST,而后端接口也可以一次性定义完所有功能,而不需要逐个开发。
再次强调,相比 REST 和 gRPC,GraphQL 是由前端决定返回结果的反模式。
使用举例:
原文推荐参考 GitHub GraphQL API
比如查询某个组织下的成员,REST 风格接口可能是:
curl -v https://api.github.com/orgs/:org/members
含义很明确,但问题是返回结果不明确,必须实际调试才知道。换成等价的 GraphQL 是这样的:
query {
organization(login: "github") {
members(first: 100) {
edges {
node {
name
avatarUrl
}
}
}
}
}
返回的结果和约定的格式结构一致,且不会有多余的字段:
{
"data": {
"organization": {
"members": {
"edges": [
{
"node": {
"name": "Chris Wanstrath",
"avatarUrl": "https://avatars0.githubusercontent.com/u/2?v=4"
}
},
{
"node": {
"name": "Justin Palmer",
"avatarUrl": "https://avatars3.githubusercontent.com/u/25?v=4"
}
}
]
}
}
}
}
但是能看出来,这样做需要一个系统帮助你写 query
,很多框架都提供这个功能,比如 apollo-client。
Webhooks
如果说 GraphQL 颠覆了前后端交互模式,那 Webhooks 可以说是彻头彻尾的反模式了,因为其定义就是,前端不主动发送请求,完全由后端推送。
它最适合解决轮询问题。或者说轮询就是一种妥协的行为,当后端不支持 Webhooks 模式时。
使用举例:
Webhooks 本身也可以由 REST 或者 gRPC 实现,所以就不贴代码了。举个常用例子,比如你的好友发了一条朋友圈,后端将这条消息推送给所有其他好友的客户端,就是 Webhooks 的典型场景。
最后作者给出的结论是,这四个场景各有不同使用场景,无法相互替代:
REST:无状态的数据传输结构,适用于通用、快速迭代和标准化语义的场景。
gRPC:轻量的传输方式,特殊适合对性能高要求或者环境苛刻的场景,比如 IOT。
GraphQL: 请求者可以自定义返回格式,某些程度上可以减少前后端联调成本。
Webhooks: 推送服务,主要用于服务器主动更新客户端资源的场景。
3 精读
REST 并非适用所有场景
本文给了我们一个更大的视角看待日常开发中的接口问题,对于奋战在一线的前端同学,接触到 90% 的接口都是非 REST 规则的 Http 接口,能真正落实 REST 的团队其实非常少。这其实暴露了一个重要问题,就是 REST 所带来的好处,在整套业务流程中到底占多大的比重?
不仅接口设计方案的使用要分场景,针对某个接口方案的重要性也要再继续细分:在做一个开放接口的项目,提供 Http 接口给第三方使用,这时必须好好规划接口的语义,所以更容易让大家达成一致使用 REST 约定;而开发一个产品时,其实前后端不关心接口格式是否规范,甚至在开发内网产品时,性能和冗余都不会考虑,效率放在了第一位。所以第一点启示是,不要埋冤当前团队业务为什么没有使用某个更好的接口约定,因为接口约定很可能是业务形态决定的,而不是凭空做技术对比从而决定的。
gRPC 是服务端交互的首选
前端同学转 node 开发时,很喜欢用 Http 方式进行服务器间通讯,但可能会疑惑,为什么公司内部 Java 或者 C++ 写的服务都不提供 Http 方式调用,而是另外一个名字。了解 gRPC 后,可以认识到这些平台都是对 RPC 方式的封装,服务器间通信对性能和延时要求非常高,所以比较适合专门为性能优化的 gRPC 等服务。
GraphQL 需要配套
GraphQL 不是 REST 的替代品,所以不要想着团队从 Http 接口迁移到 GraphQL 就能提升 X% 的开发效率。GraphQL 方案是一种新的前后端交互约定,所以上手成本会比较高,同时,为了方便前端同学拼 query,等于把一部分后端工作量转移给了前端,如果此时没有一个足够好用的平台快速查阅、生成、维护这些定义,开发效率可能不升反降。
总的来说,对外开放 API 或者拥有完整配套的场景,使用 GraphQL 是比较理想的,但对于快速迭代,平台又不够成熟的团队,继续使用标准 Http 接口可以更快完成项目。
Webhooks 解决特殊场景问题
对于第三方平台验权、登陆等 没有前端界面做中转的场景,或者强安全要求的支付场景等,适合用 Webhooks 做数据主动推送。说白了就是在前端无从参与,或者因为前端安全问题不适合参与时,就是 Webhooks 的场景。很显然 Webhooks 也不是 Http 的替代品,不过的确是一种新的前后端交互方式。
对于慢查询等场景,前端普遍使用轮询完成,这和 Socket 相比体验更弱,但无状态的特性反而会降低服务器负担,所以慢查询和即时通讯要区分对待,用户对消息及时性的敏感程度决定了使用哪种方案。
4 总结
最后,上面总结的内容一定还有许多疏漏,欢迎补充。
5 更多讨论
讨论地址是:精读《REST, GraphQL, Webhooks, & gRPC 如何选型》 · Issue #102 · dt-fe/weekly
原文发布时间为:2018-11-03 本文作者:黄子毅
本文来自云栖社区合作伙伴“前端大学”,了解相关信息可以关注“前端大学”。
精读《REST,GraphQL,Webhooks gRPC 如何选型》相关推荐
- 【韩松】Deep Gradient Comression_一只神秘的大金毛_新浪博客
<Deep Gradient Compression> 作者韩松,清华电子系本科,Stanford PhD,深鉴科技联合创始人.主要的研究方向是,神经网络模型压缩以及硬件架构加速. 论文链 ...
- 【韩松】Deep Gradient Comression
<Deep Gradient Compression> 作者韩松,清华电子系本科,Stanford PhD,深鉴科技联合创始人.主要的研究方向是,神经网络模型压缩以及硬件架构加速. 论文链 ...
- [文献阅读] Sparsity in Deep Learning: Pruning and growth for efficient inference and training in NN
文章目录 1. 前言 2. Overview of Sparsity in Deep Learning 2.1 Generalization 2.2 performance and model sto ...
- 【翻译】Batch Normalization: Accelerating Deep Network Trainingby Reducing Internal Covariate Shift
Batch Normalization: Accelerating Deep Network Trainingby Reducing Internal Covariate Shift Sergey I ...
- 模型加速--CLIP-Q: Deep Network Compression Learning by In-Parallel Pruning-Quantization
CLIP-Q: Deep Network Compression Learning by In-Parallel Pruning-Quantization CVPR2018 http://www.sf ...
- 论文笔记30 -- (视频压缩)【CVPR2021】FVC: A New Framework towards Deep Video Compression in Feature Space
<FVC: A New Framework towards Deep Video Compression in Feature Space> CVPR 2021 的一篇Oral 提出了特征 ...
- 端到端图像压缩《Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation》
Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation 一 简介 二 内容 2.1 目前方法的缺陷 2.2 整 ...
- 深度学习视频压缩1—DVC: An End-to-end Deep Video Compression Framework
本文是第一篇端到端使用神经网络来进行视频压缩的论文, github地址:GitHub - GuoLusjtu/DVC: DVC: An End-to-end Deep Video Compressio ...
- 【论文阅读】Deep Compositional Captioning: Describing Novel Object Categories without Paired Training Data
[论文阅读]Deep Compositional Captioning: Describing Novel Object Categories without Paired Training Data ...
- CVPR 2018 TRACA:《Context-aware Deep Feature Compression for High-speed Visual Tracking》论文笔记
理解出错之处望不吝指正. 本文的模型叫做TRACA.模型中使用多个expert auto-encoder,在预训练阶段,每个expert auto-encoder针对一个特定类进行训练:在tracki ...
最新文章
- 二进制_Kubernetes集群二进制部署
- 逼格高又实用的 Linux 命令,运维同仁一定要懂
- python学习手册条件-Python学习手册(第4版)pdf
- PAT甲级1122 Hamiltonian Cycle:[C++题解] 图论、模拟
- 直接拿来用!最火的Android开源项目(完结篇)(转)
- 软件工程进度条-第十二周
- antd表格显示分页怎么取消_真相!Word里怎么也删不掉的文档空白页原来是这样...
- Python~win32com~Excel
- 《成为顶级JAVA架构师的必备书籍》
- sql 获取当前之后某天的日期
- TensorFlow实现卷积、反卷积和空洞卷积
- wps office 2013 利用wps文字制作一张漂亮的座位表
- 一年有四季的c语言编程,一年是否有四季?
- html项目成员分工合作,科研项目分工如何填写
- 史密斯(smith)圆图讲解
- 在线答题小程序关于完形填空题的设计
- python过京东app图形验证勾股定理_Python爬虫模拟登录京东获取个人信息
- 关于算法工程师,你想知道的都在这里!
- java 结束循环_java中结束循环的方法
- 安装nvm时报错exit status 145和exit status 1 exit status 5