利用区块链和存储网络作为数据互操作性层
编者按: 在 ArcBlock 的产品设计中,基于 GraphQL 的 RPC 是无处不在的,我们的开发链访问协议(OCAP)的查询语言就使用了 GraphQL,我们的 ArcBlock 区块链开发框架的 RPC 服务界面也是采用了 GraphQL。为什么我们在设计上更青睐 GraphQL,而不是更常见的 REST ful 的 API,或者 JSON RPC 呢?刚好读到 Brandon Ramirez 这篇文章分享了他的看法,与我们心有戚戚焉,特此翻译推荐给大家。
作者: Brandon Ramirez
译者: 陈俊
数十年来,市面上唯一被广泛使用的数据库是 SQL 数据库,它仍然是大多数组织,软件应用和机构的核心。然而,随着区块链的到来,关系数据库终于有了替代选项,而且我谈论的不只是 NoSQL 运动带来的增量改进。我们正处于所谓去中心化网络或 Web3 等新范例的风口浪尖,其中数据(而非专有 API)是互操作性的基础。在这篇文章,我将解释为什么会发生这种转变,以及 GraphQL 查询语言如何被独特地定位以支持这个新的数据互操作时代。
专有 API 的问题
当今的万维网是通过专有的应用编程接口(API)相互连接起来,API 的存在主要是为了解决中心化(通常为 SQL)数据库的局限性。在描述事态时,以前在以太坊基金会工作的 Vinay Gupta 观察到:“当你在组织的核心拥有一个大型数据库时,该数据库可以存储所有真相和所有真知,你非常不愿意让其他人接触该数据库。”
因此,在服务器上运行的专有 API 会成为中心化数据库的保护屏障。它们限制了输入、输出、由谁,以及以什么格式。使用微服务模式,我们甚至可以将数据封装在组织内部,这样由不同团队构建的服务必须通过彼此的 API。虽然这使我们到达了今天的位置,但 API 的这种泛滥具有以下缺点:
1.API 僵化且维护成本高;
2.当前模型效率低下;
3.专有 API 导致数据垄断。
且让我们一一详解:
1. API 僵化且维护成本高
API,特别是 REST API,在设计时考虑了特定的用例,例如 Web 应用中的功能,并且你从这些用例中获得的信息越多,使用起来就越困难。
在组织内部,这导致 API 表面积不断扩大。每个新功能都需要进行额外的工程设计工作才能用新的端点来扩展 API。反过来,每个新端点都需要正在进行的工程工作来维护和支持其使用期限,这可能要花很长的时间。
同时,对于公开 API 的使用者而言,他们受制于 API 开发者决定支持的用例。Github 的生态工程总监 Kyle Daigle 明确指出了这个问题:“几乎每个 API 都通过其设计来驱动集成……我能想到的每个 API……它们都对如何使用它们有一定的主意,如果你想颠覆它,那基本上是不可能的……你必须去抓取大量数据库,将其粘贴在数据库中,并以此为基础构建自己的 API。”
这些公开 API 的刚性需要大量额外的工程工作来解决,这就引发了下一个问题。
2. 当前模型效率低下
如我们所见,API 的刚性导致大量数据库和 API 激增,它们通常以不同的格式或在不同的 API 语义之后存储完全相同的数据。这些新数据库和 API 均需要其他基础结构和工程资源来维护。
这也导致大量的迂回曲折。再次引用 Vinay Gupta 的话:“当你向国税局提交表单时,它需要经过 6 或 7 个流程才能在其数据库中显示出来……整个协作是间接的、官僚的、困难的。”
在研究这一数据问题的论文中,Brendan O’Brien 和 Michael Hucka 将 SQL 数据库的首要地位描述为“中间数据库”模式,如下所示:
任何足够简单的软件系统都将涉及无数服务器,这些服务器对来自一个数据库的数据进行编码,通过网络提供数据,对数据进行解码,将其放入另一个数据库中,并重复多次此过程。
O’Brien 和 Hucka 描述了一种常见现象:要么在这些数据管道中如何将中间结果存储在私有数据库中,要么由于要让这些数据可公开使用而需要进行的工程工作而被完全淘汰。结果是重复劳动的两个维度:在数据管道内,以及由孤立的团队和组织创建的各种数据管道之间。
3. 专有 API 导致数据垄断
将数据放入孤岛的必要性也导致道德风险。它已成为技术领域的一种常见情形,一家主要的技术巨头之前鼓励开发者在其平台上进行开发之后,撤消了对其专有 API 的访问。
Facebook 故意这样做是为了扼杀竞争,而 Twitter 则是为了更有效地利用其数据获利。InfoWorld 资深作家 Serdar Yegulalp 谈到了 Twitter 的故事,扼要叙述了开发专有 API 的风险:”称它为 API 经济的职业危害之一:对单个实体的依赖越广泛和多面化(无论是作为数据源,分析层还是基础架构),从地毯中抽出地毯越容易在你的脚下。“
要求数据置于网关之后的软件架构范例自然会引发这些数据垄断的有害实践。
为了避免失之偏颇,我应该指出基于 API 的连接已经取得了巨大的成功。通过让开发者能够用诸如 Stripe 或 Twilio 之类的小型专用服务编写软件,API 创造了不可估量的经济价值。他们为我们提供了一种在 SQL 主导的传统技术领域中的应用之间安全传输数据的方法。没有 API,我们今天所知道和喜爱的互联网将无法实现。但是现在,随着区块链和其他 Web3 技术的出现,我们有机会进入互联网无摩擦、互操作性的新时代。
进入区块链和内容寻址存储
SQL 和大多数 NoSQL 数据库的主要缺点是它接受对数据进行适当修改的信息模型。Clojure 编程语言和 Datomic 数据库的创建者 Rich Hickey 称之为“面向位置的编程(PLOP)”,尽管有必要克服小内存和磁盘尺寸的局限性,但它在现代的信息模型已不再占有一席之地。如果可以通过任意方式就地更改数据,那么就无法相信数据是正确的,或者自从上次访问以来没有发生任何更改。因此,去中心化网络的两种赋能技术:区块链和基于内容的存储,都在其信息模型中强调不变性也就不足为奇了。
内容寻址存储
尽管区块链的热度要大得多,但我将首先介绍内容寻址存储,因为它是更简单更基础的概念。这个想法是:对于任何数据片段(数据库中的实体、文件系统中的文件、CDN 上的 Blob),你如何引用这些数据?是否给它提供一个任意的 ID、URL 或名称,根据你的询问方式,它可以在不同的时间引用不同的数据……还是给它一个唯一的 ID,该 ID 可以永远永久地解析为特定值,无论它是从在你自己的本地文件系统,在远程服务器上,还是从另一个星球提供?
内容寻址存储网络,例如星际文件系统(IPFS)或分布式版本控制系统(Git),采用后一种方法,即使用从内容本身唯一来计算(使用哈希函数)ID。因为内容 ID 应该始终返回相同的内容,而后者又可以用来重新计算 ID,所以验证数据的完整性是微不足道的。
在这一点上,你可能会问自己,如果内容寻址存储是不可变的,那么我们该如何做些有用的事情呢?毕竟,在现实世界中,我们使用数据来表示的事物,例如你的银行帐户余额、你的朋友列表、你的待办事项列表,会随时间变化。我们如何使用不可变数据作为核心构建模块来表示随时间变化的概念?这就是区块链发挥作用的地方。
区块链
区块链的核心是不可变值的仅附加数据结构:一系列区块组成的链。尽管每个区块都是不可变的,但我们可以通过使变量(例如帐户余额或智能合约状态)的价值因区块而异来模拟可变性。通过这种模式,我们可以自由获得可审计性,这意味着我们可以看到任何变量随时间变化的情况,从而允许外部流程放心地直接依赖于此数据。
具有智能合约功能的区块链(例如以太坊),也为我们提供了一种方法,以编码方式修改数据片段以及用安全的方式由谁来修改数据——这通常是由中心化 API 的职责。
这两项创新开启了一个新的范例,其中存储在区块链和内容寻址网络的数据充当了互操作性层:
由于区块链被设计为去中心化、用户无需许可即可参与,且可在存在某种恶意的环境中运行,因此无需为了保护安全性和健壮性而将它们隐藏在某些额外的保护层之后。对于存在区块链或内容寻址存储网络中的数据,专有的 API 不再是架构的必需——流程可以与去中心化数据直接交互,作为实现互操作性的共享基础。
查询去中心化数据
如果区块链是一种新型的数据库原语,那么我们将如何查询该数据?是通过 RESTful API、RPC 调用,SQL 接口吗?答案将不可避免地是上述所有,但对于旨在提供在区块链之上开发构建的消费者级性能的去中心化应用,GraphQL 是自然的选择。
GraphQL 比 REST 或 RPC API 更有效
GraphQL 既是查询语言又是接口定义语言(IDL),是由 Facebook 发明和开源的。它旨在克服传统 RESTful API 的僵化和效率低下的问题,我们在之前已对此进行了讨论。它通过直接向 API 使用者展示功能强大但符合人机工程学的查询语言来实现此目的。
使用传统的 REST(表示状态传输)API,每个实体或资源都有一个单独的端点,该端点定义了你将收到的有关该实体的数据。例如,要获取用户所属组织的名称,你可能必须首先调用:
/api/v2/users/1
然后调用:
/api/v2/organizations/7
基于传统 API 构建的现实应用可能会进行数十或数百次往返网络调用。而且,这不仅仅是 REST 的问题。例如 AdChain 是一个流行的去中心化应用,它建立在以太坊 RPC API 的基础上,并被迫向 Infura 进行数百次往返网络调用以加载其 UI,从而导致网络拥塞和加载时间不理想。
截至撰写本文时,AdChain 注册表对 Infura 进行了数百次网络调用:https://publisher.adchain.com/domains
另一方面,GraphQL 功能强大,足以在单个查询中表达应用所需的所有数据。无论你需要多少数据,使用 GraphQL 都不需要进行多个网络调用。有时这称为解决获取不足问题。此外,你只需要获得所需的确切数据,而不需要获得更多数据,从而解决了过度提取的问题。
结果就是界面的使用方式就少了很多,它们只为你提供所需的数据,不需要不断更新以支持外部开发者的新用例。
对于去中心化应用,GraphQL 比 SQL 更好
但是为什么不使用某些查询语言(如 SQL)来查询数据区块链呢?
明确地说,我认为这可能并且应该发生。SQL 已在全球范围内广泛采用,为数百万的开发者所熟悉,并且比 GraphQL 作为查询语言更强大。数据科学家和数据工程师尤其熟悉,他们可能不熟悉 GraphQL。话虽如此,SQL 不会成为构建在区块链上的去中心化应用(dApps)首选的语言。
基于区块链构建的 dApp,GraphQL 会胜过 SQL 的几个主要原因:
1.GraphQL“足够强大”
2.GraphQL 对于前端开发者更符合人机工程学
3.GraphQL 旨在跨组织信任边界使用
让我们一一介绍。
1. GraphQL“足够强大”
即使 GraphQL 查询语言本身不像 SQL 那样具有丰富的表达能力,但经过精心设计的 GraphQL 端点可以为你提供你期望从 SQL 查询界面获得的大多数查询功能。例如,GraphQL 规范本身并未指定进行聚合的方式,但是出现了诸如 OpenCRUD 之类的标准,用于指定如何公开此功能。
仍然存在一些长尾功能,例如跨实体的临时连接,对于 GraphQL API 而言可能永远无法实现。但是,我估计对于前端应用所需的 99.9%用例,GraphQL 足够好。
2. GraphQL 对于前端开发者更符合人机工程学
通过选择 GraphQL,你只需付出一点点就可以适应人机工程学。例如,GraphQL 具有类似 JSON 的语法:
query {
user(id:1) {
name
organization {
name
}
}
}
而且,GraphQL 查询的响应是一个 JSON 对象,它完全反映了请求的形状。
{
“user”: {
“name”: “Vitalik”,
“organization”: {
“name”: “Ethereum Foundation”
}
}
鉴于 JSON 是用于在 Web 上传输数据的最常用数据格式,因此对于大多数 Web 开发者而言,这种语法是难以置信的易用。
同时,等效的 SQL 查询如下所示:
SELECT user.name, organization.name
FROM user JOIN organization ON (user.organization_id=organization.id)
WHERE user.id=1
这并不是最糟糕的事情,但是可以说它不如 GraphQL 查询那么直观简单。
而且,响应数据将被反规范化并以表格形式发送,并以你碰巧使用的特定 SQL 数据库的专有有线协议发送。这与 GraphQL 响应的直观嵌套相反,后者通过 HTTP 发送的纯文本 JSON 表示。
GraphQL 生态还具有诸如 React-Apollo 之类的工具,让通过 GraphQL 提取的数据直接集成到 Web 应用的 UI 组件中变得异常简单。由于几乎从未直接从移动或 Web 应用通过 HTTP 使用 SQL,因此我所知道的 SQL 生态系统中不存在这样的工具。
3. GraphQL 旨在跨信任边界使用
也许更重要的是,SQL 端点从未设计为跨组织信任边界使用的端点。例如,如果我们使用 SQL 提供只读的区块链数据,那么过于复杂的 SQL 查询足以使你的数据库进入抓取状态,从而使其他任何人都无法使用它。
GraphQL 的功能同样足够强大,可以在后端触发任意昂贵的计算,但是与 SQL 不同的是,解决该问题从一开始就成为重点关注的领域,并且越来越多的研究和工具能够动态阻止昂贵的查询和客户端节流。
同时,解决 SQL 中此问题的类似方法传统上是手动查找慢查询并简单地重写它们。或者可以添加索引或更改数据库架构,以减轻“批准的”昂贵查询的影响。这就是 SQL 始终在组织中部署的本质,只有严格控制的人员或服务才能直接查询端点。
GraphQL 的跨组织基因闪耀的另一个地方是其模式自省。GraphQL 将模式自省视为该语言的头等大事。
例如,GraphQL 中的 Root 类型具有 _schema 字段,可用于自省可查询的类型:
// GraphQL request
query {
**schema {
types {
name
description
fields {
name
}
}
}
}
// JSON response
{
“data”: {
“**schema”: {
“types”: [
{
“name”: “Root”,
“description”: null
},
{
“name”: “User”,
“description”: “A user of the platform.”
“fields”: [
{ “name”: “name” },
{ “name”: “id” }
]
},
{
“name”: “Organization”,
“description”: “An organization of the platform.”
“fields”: [
{ “name”: “name” },
{ “name”: “id” }
]
}
]
}
}
}
为了对 SQL 公平起见,尽管一些自省查询看起来确实很恐怖,但是如果你熟悉以下语法,则上述内容的大部分自省看起来并不可怕:
SELECT c.table_schema,c.table_name,c.column_name,pgd.description
FROM pg_catalog.pg_description pgd
RIGHT JOIN information_schema.columns c on
(pgd.objsubid=c.ordinal_position)
WHERE c.table_schema NOT IN (‘pg_catalog’, ‘information_schema’);
然而,这一 SQL 查询充满了 Postgres 数据库的供应商特定的参数。MySQL 数据库的等效查询将有所不同。另外,尽管上述查询很容易以纯文本形式阅读,但发送查询和接收响应却需要特殊的工具:特定供应商的 CLI 客户端或跨供应商的桌面 GUI,可以理解特定供应商的 SQL 风格,有线协议,ODBC 或以上各项的组合。
另一方面,GraphQL 会针对所有查询(包括自省查询)通过 HTTP 返回纯文本 JSON,以便你可以使用 Postman、Chrome 开发工具或预装在每台 Mac 和 Linux 操作系统终端上的简单 curl 命令踢除端点上的烦恼。
结论
确实,我所强调的 REST 和 SQL 的许多缺点并非没有补救措施。人们一直在努力解决 RESTful API 的获取过度和不足的问题。一直存在将架构添加到 RESTful API 中的努力,理论上可以从预定义的端点提供服务。SQL 还是一种查询语言,而不是一种实现,因此,没有什么可以阻止我们构建使用 HTTP,通过网络返回纯文本 CSV 或 JSON 并具有更明智的自省功能的 SQL 接口。但是,像现在启用区块链和基于内容寻址的存储网络一样,跨组织信任边界直接有效地查询任意数据根本不存在这两种技术中的任何一种的基因之中。
同时,GraphQL 是针对该用例进行全新设计的。它的设计考虑了对前端工程师用户友好的图形界面,和能够几乎无缝地将 GraphQL 查询声明性绑定到浏览器中的 UI 组件的成熟工具。在 dApp 主要由与运行在区块链上的智能合约接口的浏览器应用组成的范例中,前端工程师的需求和偏好将成为确定去中心化 Web 技术堆栈的动力。这就是为什么我们已经看到了为什么有很多努力将 GraphQL 接口放在以太坊的 JSON RPC API。
在 Graph,我们认为在区块链之上建立具有消费者级性能的丰富用户体验是实现区块链和去中心化网络广泛普及的主要障碍之一。因此,去年 7 月我们开放了索引服务器的源代码,让开发者可以通过 GraphQL 接口有效地查询以太坊和 IPFS 数据,以了解其去中心化应用。将来,随着数据科学和区块链上机器学习的分析管道成为更常见的用例,我们将着眼于支持 SQL 以及其他查询语言……Datalog,有人用吗?
来源: Medium 文章 GraphQL Will Power the Decentralized Web[1]
References
[1] GraphQL Will Power the Decentralized Web: https://medium.com/graphprotocol/graphql-will-power-the-decentralized-web-d7443a69c69a