Web3.0应用程序架构
Web 3.0 应用程序(或“DApps”)的架构与 Web 2.0 应用程序完全不同。
以博客园为例,这是一个简洁的博客网站,用户可以发布自己的内容并可以评论他人的内容进行互动。
作为一个 web 2.0 应用程序,可能听起来很简单,但是博客园的架构中包含了很多东西可以才让这一切成为可能:
-
首先,必须有一个地方来存储基本数据,例如用户、文章、标签、评论、推荐、反对等。这需要一个即时更新的数据库。
-
其次,后端代码(用 Go、Java、PHP 或 Python 等语言编写)必须定义博客园的业务逻辑。例如,当新用户注册、发布新博客或在其他人的博客上发表评论时会发生什么?
-
第三,前端代码(通常用 JavaScript、HTML 和 CSS 编写)必须定义博客园的 UI 逻辑。例如,网站是什么样的,当用户与页面上的每个元素交互时会发生什么?
综上所述,当你在博客园上写一篇博客文章时,你会与它的前端交互,前端与后端通信,后端与它的数据库通信。所有这些代码都托管在集中式服务器上,并通过互联网浏览器发送给用户。这是对当今大多数 Web 2.0 应用程序如何工作的一个概括性总结。
但这一切都在改变。
区块链技术为 Web 3.0 应用开启了一个激动人心的新方向。在本文中,我们将重点关注以太坊区块链带来的好处。
是什么让Web3.0与众不同?
与博客园等 Web 2.0 应用程序不同,Web 3.0 消除了中间人。没有存储应用程序状态的集中式数据库,也没有后端逻辑所在的集中式 Web 服务器。
相反,您可以利用区块链在由互联网上的匿名节点维护的分散状态机上构建应用程序。
“状态机”(state machine)是指一台机器,它维护一些给定的程序状态和该机器上允许的未来状态。区块链是用一些初始状态实例化的状态机,并且具有非常严格的规则(即共识)来定义该状态如何转换。
更好的是,没有任何一个实体可以控制这个分散的状态机 —— 它由网络中的每个人共同维护。
那么后端服务器呢?在 Web 3.0 中,您可以编写定义应用程序逻辑并将它们部署到去中心化状态机上的智能合约,而不是如何控制博客园的后端。这意味着每个想要构建区块链应用程序的人都将他们的代码部署在这个共享状态机上。
前端呢?它几乎保持不变,除了一些例外,我们将在后面介绍。
这是架构的样子:
透过现象看本质
现在,让我们更深入地了解是什么使这成为可能。
区块链(blockchain)
以太坊区块链经常被吹捧为“世界计算机”。 这是因为它是一个全局可访问的确定性状态机,由对等节点网络维护。 此状态机上的状态更改受网络中对等方遵循的共识规则的约束。
因此,换句话说,它实际上被设计为世界上任何人都可以访问和写入的状态机。 因此,这台机器不属于任何单一实体,而是由网络中的每个人共同拥有。
还有一件事要知道:数据只能写入以太坊区块链——你永远无法更新现有数据。
智能合约(smart contracts)
智能合约是在以太坊区块链上运行的程序,它定义了区块链上发生的状态变化背后的逻辑。智能合约是用高级语言编写的,例如 Solidity 或 Vyper。
由于智能合约代码存储在以太坊区块链上,任何人都可以检查网络上所有智能合约的应用逻辑。
以太坊虚拟机(Ethereum Virtual Machine,EVM)
接下来,你有以太坊虚拟机,它执行智能合约中定义的逻辑并处理在这个全局可访问的状态机上发生的状态变化。
EVM 不理解用于编写智能合约的高级语言,如 Solidity 和 Vyper。相反,您必须将高级语言编译成字节码,然后 EVM 可以执行该字节码。
前端(front-end)
最后,我们有前端。正如我们之前提到的,它定义了 UI 逻辑,但前端也与智能合约中定义的应用程序逻辑进行通信。
前端和智能合约之间的通信比上图中显示的要复杂一些。接下来让我们仔细看看这个。
前端代码如何与以太坊上的智能合约通信?
我们希望我们的前端与我们的智能合约进行通信,以便它们可以调用函数,但请记住,以太坊是一个去中心化的网络。 以太坊网络中的每个节点都会在以太坊状态机上保存一份所有状态的副本,包括与每个智能合约相关的代码和数据。
当我们想要与区块链上的数据和代码进行交互时,我们需要与这些节点之一进行交互。 这是因为任何节点都可以广播在 EVM 上执行交易的请求。 然后矿工将执行交易并将结果状态更改传播到网络的其余部分。
广播新交易有两种方式:
- 设置您自己的运行以太坊区块链软件的节点
- 使用 Infura、Alchemy 和 Quicknode 等第三方服务提供的节点
如果您使用第三方服务,则不必自己处理运行全节点的所有麻烦事。毕竟,在你自己的服务器上设置一个新的以太坊节点可能需要几天时间。(有很多数据需要同步——它甚至会占用比典型笔记本电脑所能处理的更多的带宽和存储空间。)
此外,存储完整的以太坊区块链的成本会随着 DApp 的扩展而增加,您需要添加更多节点来扩展您的基础设施。这就是为什么随着您的基础架构变得越来越复杂,您将需要全职的 DevOps 工程师。他们将帮助您维护基础设施,以确保可靠的正常运行时间和快速的响应时间。
总而言之,避免这些令人头疼的问题就是为什么许多 DApp 选择使用 Infura 或 Alchemy 等服务来为他们管理节点基础设施。当然,有一个权衡,因为这会创建一个集中的阻塞点,但让我们把那个兔子洞留到另一天。
继续,让我们谈谈供应商。当您需要与区块链交互时连接的节点(无论是您自己设置还是使用来自第三方服务的现有节点)通常称为“提供者(providers)”。
每个以太坊客户端(即提供者)都实现了 JSON-RPC 规范。这确保了当前端应用程序想要与区块链交互时有一套统一的方法。如果您需要 JSON-RPC 入门,它是一种无状态、轻量级的远程过程调用 (RPC) 协议,它定义了多种数据结构及其处理规则。它与传输无关,因此这些概念可以在同一进程、套接字、HTTP 或许多不同的消息传递环境中使用。它使用 JSON (RFC 4627) 作为数据格式。
通过提供者连接到区块链后,您可以读取存储在区块链上的状态。但是,如果你想写入状态,在将交易提交到区块链之前,你还需要做一件事——使用你的私钥“签署”交易。
例如,假设我们有一个 DApp 可以让用户阅读或发布博客文章到区块链。您可能在前端有一个按钮,允许任何人查询特定用户撰写的博客文章。(回想一下,从区块链读取数据不需要用户签署交易。)
但是,当用户想要在链上发布新帖子时,我们的 DApp 会要求用户使用他们的私钥“签署”交易——只有这样 DApp 才会将交易中继到区块链。否则,节点不会接受交易。
这种交易的“签名”是 Metamask 通常出现的地方。
Metamask 是一种工具,可以让应用程序轻松处理密钥管理和事务签名。这很简单:Metamask 将用户的私钥存储在浏览器中,每当前端需要用户签署交易时,它就会调用 Metamask。
Metamask 还提供了与区块链的连接(作为“提供者”),因为它已经与 Infura 提供的节点建立了连接,因为它需要它来签署交易。这样,Metamask 既是提供者又是签名者。 🤯
区块链上的存储
当然,如果您正在构建一个所有智能合约和数据都完全位于以太坊区块链上的应用程序,那么这种架构是有意义的。但是任何在以太坊上构建应用程序的人都知道,将所有内容存储在区块链上会变得非常昂贵、非常快。
请记住,对于以太坊,用户每次向区块链添加新数据时都需要付费。这是因为向去中心化状态机添加状态会增加维护该状态机的节点的成本。
每次交易需要添加新状态时,要求用户为使用你的 DApp 支付额外费用并不是最好的用户体验。解决此问题的一种方法是使用去中心化的链下存储解决方案,例如 IPFS 或 Swarm。
IPFS 是用于存储和访问数据的分布式文件系统。因此,IPFS 系统不是将数据存储在集中式数据库中,而是将数据分发和存储在对等网络中。这使您可以在需要时轻松检索它。
IPFS 还有一个称为“Filecoin”的激励层。这一层激励世界各地的节点存储和检索这些数据。您可以使用 Infura(为您提供 IPFS 节点)或 Pinata(提供易于使用的服务,您可以将文件“固定”到 IPFS 并获取 IPFS 哈希并将其存储在区块链上)之类的提供商.
Swarm 的相似之处在于它是一个去中心化的存储网络,但有一个显着的区别。虽然 Filecoin 是一个单独的系统,但 Swarm 的激励系统是内置的,并通过以太坊区块链上的智能合约执行,用于存储和检索数据。
所以现在,使用 IPFS 或 Swarm,我们的应用程序架构如下所示:
精明的读者可能还注意到,在下图中,前端代码并未存储在区块链上。 我们可以像通常在 Web 2.0 中那样在 AWS 上托管此代码,但这会为您的 DApp 创建一个集中化的阻塞点。如果 AWS 出现故障怎么办? 如果它审查你的应用程序怎么办?
这就是为什么,如果你想构建一个真正去中心化的应用程序,你可能会选择将你的前端托管在一个去中心化的存储解决方案上,比如 IPFS 或 Swarm。
所以现在你的应用程序架构看起来更像这样:
查询区块链
到目前为止,我们已经讨论了如何通过签署交易然后将它们发送到区块链来写入区块链。但是从区块链上的智能合约中读取数据呢?有两种主要方法可以做到这一点:
(1)智能合约事件(Smart Contract Events)
您可以使用 Web3.js 库来查询和监听智能合约事件。您可以监听特定事件并在每次触发事件时指定回调。 例如,如果您有一个智能合约在每个区块中从 A 人向 B 人发送连续付款流,那么您可以在每次向 B 人进行新付款时发出一个事件。您的前端代码可以监听被触发的事件 通过智能合约并基于它执行特定的操作。
(2)The Graph
上述方法有效,但有一些局限性。例如,如果你部署了一个智能合约,后来意识到你需要一个你最初没有包含的事件,该怎么办?不幸的是,您必须使用该事件和数据重新部署新的智能合约。此外,使用回调来处理各种 UI 逻辑会很快变得非常复杂。
这就是“The Graph”的用武之地。
The Graph 是一种链下索引解决方案,可以更轻松地查询以太坊区块链上的数据。 图表允许您定义要索引的智能合约、要侦听的事件和函数调用,以及如何将传入事件转换为前端逻辑(或任何使用 API)可以使用的实体。 它使用 GraphQL 作为一种查询语言,许多前端工程师都喜欢这种语言,因为它与传统的 REST API 相比更具表现力。
通过索引区块链数据,The Graph 让我们能够以低延迟查询应用程序逻辑中的链上数据。
现在,您的 DApp 架构如下所示:
我们几乎完成了,但我们还剩下一个主要话题:扩展。
扩展你的 DApp
你可能听说过,以太坊无法扩展 —— 至少目前还没有。
显然,我们这里有问题。在以太坊上以高昂的gas费和完整的区块构建 DApp 会导致非常糟糕的用户体验。值得庆幸的是,有一些解决方案正在开发中。
一种流行的扩展解决方案是多边形,一种 L2 扩展解决方案。 Polygon 没有在主区块链上执行交易,而是拥有处理和执行交易的“侧链”。 侧链是与主链交互的二级区块链。每隔一段时间,侧链就会将其最近区块的聚合提交回主链。
L2 解决方案的其他示例是 Optimistic Rollups 和 zkRollups。这里的想法是相似的:我们使用“汇总”智能合约在链下批量交易,然后定期将这些交易提交到主链。
带回家的想法是这样的:L2 解决方案在链下进行交易执行(即慢速部分),只有交易数据存储在链上。这让我们可以扩展区块链,因为我们不必在链上执行每一笔交易。这也使交易更快、更便宜 —— 并且在必要时它们仍然可以与主要的以太坊区块链进行通信。
拼凑起来
如果所有这些都让您头晕目眩,那么您并不孤单。将所有这些工具拼凑在一起很复杂,并且可能会导致痛苦的开发人员体验。但别担心——我们开始看到新的开发者框架真正改善了开发者的体验。
例如,Hardhat 是一个开发者框架,它使以太坊开发者更容易构建、部署和测试他们的智能合约。Hardhat 提供了“Hardhat Network”,开发人员可以使用它来将他们的智能合约部署到本地网络上——而无需处理实时环境。更好的是,它提供了一个很棒的插件生态系统,让开发人员的生活变得更加轻松。Hardhat 还提供了类似于 javascript 的 console.log() 功能,用于调试目的。
当然,这仅仅是开始。我希望我们在未来继续看到更好的开发者工具。
结论
大多数人花费数月时间来弄清楚工具链是如何工作的,所以如果你是一个新的 DApp 开发人员,我希望这篇文章能为你节省一些时间。