乐趣区

【译】为什么我们对我们的API中使用GraphQL

本文是对 Why we used GraphQL for our API 的翻译,如有侵权等其他问题,请联系笔者删除。
最近在 Mavel 我们发布了 Platform API, 我们想利用整合的力量,将这个力量直接放入每天使用 Marvel 的人们的创意社区中,因此我们能更加无缝地工作 - 与日常服务工具一起工作。
什么是一个好的 API
如果我们曾经写过一个好的 API, 首先我们需要想想什么是一个好的 API。因此我们确定了设计任何 API 的良好实践,无论是否是在网络上。

很棒的文档即使是最改变生活的工具,我不能发现如何去使用,对于自己而言都是无用的。

不必要的复杂度不必要的复杂是为了官僚,我们总是更喜欢简单

缺乏惊喜因为一些事情用你没有预料的的方式运作,或者因为没有预料到的副作用被抓到是不好玩的。事情应该尽可能的简单明了。

我们可以考虑归档出这些点作为开发者体验。这对我们是用意义的 – 当我们设计 app 或者 web 界面,我们会尽量去保持用户体验。API 是针对开发者特定的界面,我们也应该做同样的事情。
其他的 APIs 哪里有欠缺
没有标准化
过去五年大多数的 web APIs 是 REST(ish) 和 json, 而不是稍微有点老的 SOAP,RPC, 或者自定义的 XML。通常,这被视为一件好事,我们看到了 APIs 的激增,由于设备更加智能和服务已经开始更加紧密的协同工作。
问题是虽然 json 已经变成 web APIs 之间发送数据的标准,但是每个 API 由于其独一无二的结构和能力,并且没有标准的方式去描述自身。当每个 API 和最后一个不同时,无法构建适合所有的工具。
因此尽管你们正在使用的 API 或者一些便利的工具,如:编辑器集成工具或者客户端库,可能很完美的被良好的文档支持。
您习惯性地使用的工具可能无法使用您正在使用的 API,或者,如果有的话,过于通用,帮助您解决问题独特的部分。事实上,这意味着您没有任何工具。
移动网络和设备
随着越来越多的网络流量被过渡到移动设备,产生了另个一个问题。移动端设备位于好延迟低带宽的不可靠的网络上。
REST API 通常要求客户端命中多端去收集呈现视图的多种资源数据(例:在两个单独的调用去获取用户的配置文件和喜欢的菜单)
因为移动端网络比其他网络更不可靠,因此当发送多个请求的时候失败的概率更高。这可能使得您获取到部分数据而不能渲染视图,或者渲染占位符当您去重新请求的时候。
与此同样糟糕的是,网络延迟是一个大的性能杀手。延迟是两个设备之间传送数据的时间,比如您的手机和 Marvel 的服务器。当设备和服务器之间的延迟是 50ms, 意味着数据从设备到服务器间传送需要 50ms,RTT(往返时间) 是 100ms.100ms 听起来不算长,但是您必须考虑到发送单个请求不止一次往返。当您接收数据或者发送数据之前,需要进行 DNS 查询,TLS 加密握手以及 TCP 三次握手,这些都需要一次或者多次往返。我们使用的在网络上传输字节的 TCP 协议也需要不断的确认收到的数据,确保丢失的包可以重传。令人悲伤的是,这些确认遵循物理规律,也需要花费往返时间,这给整个网路设置了一个上限,它直接与网络延迟紧密相关。
在高延迟的网络中,发送一个包往返时间可能需要 1s 或者更长的时间。网络延迟极大的超出了 app 开发者的控制,因此我们需要减少请求来尽可能减少它的影响。
另一个对移动端不成比例地对移动端设备影响的问题是过度获取。通常一端返回资源的完整表示, 但很有可能客户端不一定需要或者想要所有数据,大多数时候需要的是这些数据的子集。尽管如此,服务器仍旧发送无关的数据,并且客户端对这件事没有发言权。
从 API 端点获取数据的时,很有可能客户端不想要或需要返回的所有数据,但是仍旧需要支付传送和处理的费用,浪费了带宽和 CPU 周期,造成更长的响应时间,没有任何好处。
这些问题的解决方式是什么
有一些开源项目试图去解决 REST APIs 的一些问题,亦即 swagger(OpenAPI)和 API Blueprint。对于 swagger 我们已经有了一点内部经验(但是不是特别开心,yaml 可能是地狱),并向我们现有的 API 添加新端的时候试用 API BluePrint, 但是发现在 MSON 中的小的错误很难被追踪(并不比 yaml 好多少)。
尽管这些工具的承诺是很好,他们有一件事情做对了:它们强迫您为 API 定义一个模式,这个模式好像是系统边界文档一样,系统边界通常是最能感受到集成痛苦的地方。一旦你获取到一个模式,你能用它做各种各样酷炫的东西:生成文档页面,启动模拟服务器进行开发,如果你有倾向,甚至能生成客户端 API 代码。因为模式是被标准方式具体化的,因此 API 构建工具是很容易在使用相同标准的 API 之间进行移植,因为一切都是提前定义的,你的 API 消费者确切地知道他们的期望是什么以及对您的期望是什么。
这也正是 GraphQL 做正确的事情,GraphQL 定义包含客户端可用所有数据类型、更改和查询的模式。这样每个人都知道他们的立场。我能立刻确切地明白我能获取那种操作,它们接受那种类型作为输入,返回那种类型作为输出。
尽管 swagger 和 API Blueprint 在请求和响应体中携带一个模式,但是它们不能处理过度获取和发送多个请求的问题。如果您将在您的 API 中解决这些问题,那么它将是自定义的、非标准的、是单个 API 独有的。通常,您最终会为特定端点编写视图。对于前面提到的例子,这意味着有一端会立刻返回用户和菜单数据。那只是单个视图,在您的应用中有多少个独特的视图?这可能会变得混乱。
那么为什么是 GraphQL
不想 REST,GraphQL 的核心思想与解决这些问题紧密相关。每次调用仅仅返回在这次请求特定的数据,这有一些好处。首先,完全通过放在客户端手中,解决了过度请求的问题。第二,它通过需要客户端立刻请求它们所需要的数据移除了多次请求的需求。这种方式的第三个优点是,它允许我们作为 API 的操作者去确切的查看谁正在请求每个字段的人,这使得我们随着时间的流逝更容易弃用有一些字段,让新的集成商不去使用,并且返回所有存在的集成的列表,并且与他们取得联系提供升级路径。
正如我前面提到的,工具也是我们考虑的一个因素,所有上述被提及的解决方案有一些相同的工具和相对健康的社区,但是 GraphQL 超越了其他两个。Gra 主要被非常大很活跃的 react 社区。这意味着大量优秀的工具使得开发者的体验尽可能的好。
比如,连接您的编辑器到模式,对您的查询划线,在您有机会之前它们之前对错误进行标注,将其与自动完成功能相集成,当您输入的时候,能为您提供一些建议。

我喜欢的工具之一的是 GraphiQL,这是一个为浏览器中运行的 GraphQL APIs 构建的 IDE。正如下图您看到的,GraphiQL 给您提供编地方去写查询(具有您期待的功能:语法高亮,自动补全),查看结果和参考文档。

它基于浏览器意味着我们能够把它放在任何公共的地方(如 Mavel 所做的那样)并且允许某人立刻在友好的开发环境中获取我们的 API。事实证明是一个有效的方式去控制 GraphQL 本身以及 API 的细节,真正地帮助人们开始去运行。
除了它带来的其他好处之外,这也是我们选择使用 GraphQL 的原因,它简单的运行我们提供比其它替代方案更好的开发者体验。

退出移动版