indexing > Indexer Tooling > 运营Graph节点

运营Graph节点

Reading time: 26 min

Graph节点是索引子图的组件,并使生成的数据可通过GraphQL API进行查询。因此,它是索引人堆栈的中心,Graph节点的正确运作对于运行成功的索引人至关重要。

这提供了Graph节点的背景概述,以及索引人可用的一些更高级的选项。可以在Graph 节点存储库中找到详细的文档和说明。

Graph 节点

链到本节

Graph Node是Graph Network上索引子图、连接到区块链客户端、索引子图并使索引数据可供查询的参考实现。

Graph节点(以及整个索引人堆栈)可以在裸机上运行,也可以在云环境中运行。中央索引组件的这种灵活性对于图形协议的有力性至关重要。类似地,Graph 节点可以从源代码构建,或者索引人可以使用提供的Docker Images之一。

PostgreSQL 数据库

链到本节

Graph节点的主存储区,这是存储子图数据、子图元数据以及子图不可知的网络数据(如区块缓存和eth_call缓存)的地方。

网络客户端

链到本节

为了索引网络,Graph节点需要通过以太坊兼容的JSON-RPC访问网络客户端。此RPC可能连接到单个以太坊客户端,也可能是跨多个客户端进行负载平衡的更复杂的设置。

虽然有些子图可能只需要一个完整的节点,但有些子图的索引功能可能需要额外的RPC功能。特别是,将eth_calls作为索引的一部分的子图需要一个支持EIP-1898的归档节点,而带有callHandlers或带有调用筛选器的blockHandlers的子图则需要trace_filter支持(请参阅此处的跟踪模块文档)

Network Firehoses - a Firehose is a gRPC service providing an ordered, yet fork-aware, stream of blocks, developed by The Graph's core developers to better support performant indexing at scale. This is not currently an Indexer requirement, but Indexers are encouraged to familiarise themselves with the technology, ahead of full network support. Learn more about the Firehose here.

IPFS节点

链到本节

子图部署元数据存储在IPFS网络上。Graph节点主要在子图部署期间访问IPFS节点,以获取子图清单和所有链接文件。网络索引人不需要托管自己的IPFS节点。网络的IPFS节点托管于https://ipfs.network.thegraph.com。

Prometheus指标服务器

链到本节

为了实现监控和报告,Graph节点可以选择将指标记录到Prometheus指标服务器。

从来源开始

链到本节

安装先决条件

链到本节
  • PostgreSQL

  • IPFS

  • Ubuntu 用户的附加要求 - 要在 Ubuntu 上运行 Graph 节点,可能需要一些附加的软件包。

sudo apt-get install -y clang libpq-dev libssl-dev pkg-config

设置

链到本节
  1. 启动 PostgreSQL 数据库服务器
initdb -D .postgres
pg_ctl -D .postgres -l logfile start
createdb graph-node
  1. 克隆Graph 节点repo,并通过运行 cargo build来构建源代码。

  2. 现在,所有的依赖关系都已设置完毕,启动 Graph节点。

cargo run -p graph-node --release -- \
--postgres-url postgresql://[USERNAME]:[PASSWORD]@localhost:5432/graph-node \
--ethereum-rpc [NETWORK_NAME]:[URL] \
--ipfs https://ipfs.network.thegraph.com

Kubernetes入门

链到本节

完整的Kubernetes示例配置可以在索引人存储库中找到。

端口

链到本节

当运行Graph Node时,会暴露以下端口:

端口用途路径CLI 参数环境 变量
8000GraphQL HTTP 服务
(用于子图查询)
/subgraphs/id/...

/subgraphs/name/.../...
--http-port-
8001GraphQL WS
(用于子图订阅)
/subgraphs/id/...

/subgraphs/name/.../...
--ws-port-
8020JSON-RPC
(用于管理部署)
/--admin-port-
8030子图索引状态 API/graphql--index-node-port-
8040Prometheus 指标/metrics--metrics-port-

重要: 公开暴露端口时要小心 - 管理端口 应保持锁定。 这包括下面详述的 Graph 节点 JSON-RPC 和索引人管理端点。

高级 Graph 节点配置

链到本节

最简单的是,Graph节点可以使用Graph节点的单个实例、单个PostgreSQL数据库、IPFS节点和要索引的子图所需的网络客户端来操作。

通过添加多个Graph节点和多个数据库以支持这些Graph节点,可以水平扩展此设置。高级用户可能希望通过config.toml文件和Graph节点的环境变量,利用Graph节点的一些水平扩展功能以及一些更高级的配置选项。

config.toml

链到本节

TOML配置文件可用于设置比CLI中公开的配置更复杂的配置。文件的位置通过--config命令行开关传递。

使用配置文件时,不能使用选项--postgres-url、--postgres-secondary-hosts和--postgres-host-weights。

可以提供最小的config.toml文件;以下文件等效于使用--postgres-url命令行选项:

[store]
[store.primary]
connection="<.. postgres-url argument ..>"
[deployment]
[[deployment.rule]]
indexers = [ "<.. list of all indexing nodes ..>" ]

config.toml的完整文档可以在Graph Node文档中找到。

多个 Graph 节点

链到本节

Graph Node indexing can scale horizontally, running multiple instances of Graph Node to split indexing and querying across different nodes. This can be done simply by running Graph Nodes configured with a different node_id on startup (e.g. in the Docker Compose file), which can then be used in the config.toml file to specify dedicated query nodes, block ingestors, and splitting subgraphs across nodes with deployment rules.

请注意,可以将多个Graph节点配置为使用同一个数据库,该数据库本身可以通过分片进行水平扩展。

部署规则

链到本节

给定多个Graph节点,有必要管理新子图的部署,以便同一子图不会被两个不同的节点索引, 这会导致冲突。这可以通过使用部署规则来实现,如果正在使用数据库shard,部署规则还可以指定子图的数据应该存储在哪个分片中。部署规则可以与子图名称和部署所索引的网络相匹配,以便做出决策。

部署规则配置示例:

[deployment]
[[deployment.rule]]
match = { name = "(vip|important)/.*" }
shard = "vip"
indexers = [ "index_node_vip_0", "index_node_vip_1" ]
[[deployment.rule]]
match = { network = "kovan" }
# No shard, so we use the default shard called 'primary'
indexers = [ "index_node_kovan_0" ]
[[deployment.rule]]
match = { network = [ "xdai", "poa-core" ] }
indexers = [ "index_node_other_0" ]
[[deployment.rule]]
# There's no 'match', so any subgraph matches
shards = [ "sharda", "shardb" ]
indexers = [
"index_node_community_0",
"index_node_community_1",
"index_node_community_2",
"index_node_community_3",
"index_node_community_4",
"index_node_community_5"
]

此处阅读有关部署规则的更多信息。

专用查询节点

链到本节

通过在配置文件中包含以下内容,可以将节点配置为显式查询节点:

[general]
query = "<regular expression>"

任何--node-id与正则表达式匹配的节点都将被设置为只响应查询。

通过分片扩展数据库

链到本节

对于大多数用例,单个Postgres数据库足以支持graph节点实例。当一个graph节点实例超过一个Postgres数据库时,可以将graph节点的数据存储拆分到多个Postgres数据库中。所有数据库一起构成graph节点实例的存储。每个单独的数据库都称为分片。

分片可用于在多个数据库中拆分子图部署,也可用于使用副本在数据库之间分散查询负载。这包括配置每个graph-node 应在其连接池中为每个数据库保留的可用数据库连接,随着索引的子图越来越多,这一点变得越来越重要。

当您的现有数据库无法跟上Graph节点给它带来的负载时,以及当无法再增加数据库大小时,分片变得非常有用。

在开始使用分片之前,通常最好使单个数据库尽可能大。一个例外是查询流量在子图之间分配非常不均匀;在这些情况下,如果将高容量子图保存在一个分片中,而将其他所有内容都保存在另一个分片上,这会有很大的帮助,因为这种设置使高容量子图的数据更有可能保留在数据库内部缓存中,而不会被低容量子图中不需要的数据所取代。

在配置连接方面,首先将 postgresql.conf 中的 max_connections 设置为400(或甚至200),然后查看 store_connection_wait_time_ms 和 store_connecion_checkout_count Prometheus 度量。明显的等待时间(任何超过5ms的时间)表明可用连接太少;高等待时间也将由数据库非常繁忙(如高CPU负载)引起。然而,如果数据库在其他方面看起来很稳定,那么高等待时间表明需要增加连接数量。在配置中,每个graph节点实例可以使用的连接数是一个上限,如果不需要,Graph节点将不会保持连接打开。

此处阅读有关存储配置的更多信息。

专用区块摄取

链到本节

如果配置了多个节点,则需要指定一个负责接收新区块的节点,这样所有配置的索引节点都不会轮询链头。这是作为chains命名空间的一部分完成的,指定用于区块摄取的node_id

[chains]
ingestor = "block_ingestor_node"

支持多个网络

链到本节

Graph协议正在增加支持索引奖励的网络数量,并且存在许多索引不支持的网络的子图,索引人希望处理这些子图。config.toml文件允许表达和灵活配置:

  • 多个网络。
  • 每个网络有多个提供程序(这可以允许跨提供程序分配负载,也可以允许配置完整节点和归档节点,如果给定的工作负载允许,Graph Node更喜欢便宜些的提供程序)。
  • 其他提供商详细信息,如特征、身份验证和提供程序类型(用于实验性Firehose支持)。

[chains]部分控制graph节点连接到的以太坊提供程序,以及每个链的区块和其他元数据的存储位置。以下示例配置了两个链,mainnet和kovan,其中mainnet的区块存储在vip分片中,而kovan的区块则存储在主分片中。主网链可以使用两个不同的提供商,而kovan只有一个提供商。

[chains]
ingestor = "block_ingestor_node"
[chains.mainnet]
shard = "vip"
provider = [
{ label = "mainnet1", url = "http://..", features = [], headers = { Authorization = "Bearer foo" } },
{ label = "mainnet2", url = "http://..", features = [ "archive", "traces" ] }
]
[chains.kovan]
shard = "primary"
provider = [ { label = "kovan", url = "http://..", features = [] } ]

此处阅读有关存储配置的更多信息。

环境变量

链到本节

Graph节点支持一系列环境变量,这些变量可以启用特征或更改Graph节点的行为。这些都记录在这里

持续部署

链到本节

使用高级配置操作缩放索引设置的用户可以从使用Kubernetes管理Graph节点中受益。

  • 索引人存储库有一个示例Kubernetes引用
  • Launchpad是一个工具包,用于在GraphOps维护的Kubernetes上运行Graph Protocol Indexer。它提供了一组Helm图表和一个CLI来管理Graph Node部署。

管理Graph节点

链到本节

给定一个正在运行的 Graph 节点(或多個 Graph 节点!),接下来的挑战是如何跨这些节点管理部署的子图。Graph 节点覆盖了一系列工具,以帮助管理子图。

日志

链到本节

Graph节点的日志可以为Graph节点和特定子图的调试和优化提供有用的信息。Graph节点通过GRAPH_LOG环境变量支持不同的日志级别,具有以下级别:错误、警告、信息、调试或跟踪。

此外,将GRAPH_LOG_QUERY_TIMING设置为gql提供了有关GraphQL查询如何运行的更多详细信息(尽管这将生成大量日志)。

监控& 警报

链到本节

默认情况下,Graph Node通过8040端口上的Prometheus端点提供指标。然后可以使用Grafana来可视化这些指标。

索引人存储库提供了Grafana配置示例

Graphman

链到本节

graphman是Graph节点的维护工具,帮助诊断和解决不同的日常和异常任务。

Graphman命令包含在官方容器中,您可以将docker exec插入到 Graph 节点容器中运行它。它需要一个config.toml文件。

Graph节点存储库中提供了graphman命令的完整文档。参见[/docs/graphman.md] (https://github.com/graphprotocol/graph-node/blob/master/docs/graphman.md)Graph节点`/docs`

使用子图

链到本节

索引状态API

链到本节

默认情况下,在端口8030/graphql上可用,索引状态API公开了一系列方法,用于检查不同子图的索引状态、检查索引证明、检查子图特征等。

此处提供完整的模式。

索引性能

链到本节

索引过程有三个独立的部分:

  • 正在从提供程序获取感兴趣的事件
  • 使用适当的处理程序按顺序处理事件(这可能涉及调用状态链,并从存储中获取数据)
  • 将生成的数据写入存储

这些阶段是流水线的(即可以并行执行),但它们彼此依赖。如果子图索引速度慢,则根本原因将取决于特定的子图。

索引速度慢的常见原因:

  • 从链中查找相关事件所需的时间(特别是调用处理程序可能慢,因为依赖trace_filter
  • 将大量eth_calls作为处理程序的一部分
  • 执行期间大量的存储交互
  • 要保存到存储的大量数据
  • 要处理的大量事件
  • 拥挤节点的数据库连接时间慢
  • 提供商本身落后于链头
  • 在链头从提供商获取新收据的速度较慢

子图索引度量可以帮助诊断索引速度慢的根本原因。在某些情况下,问题在于子图本身,但在其他情况下,改进的网络提供商、减少的数据库冲突和其他配置改进可以显著提高索引性能。

失败的子图

链到本节

在为子图编制索引期间,如果遇到意外数据、某些组件未按预期工作,或者事件处理程序或配置中存在错误,则子图可能会失败。有两种常见的故障类型:

  • 确定性故障:这些故障不会通过重试解决
  • 非确定性故障:这些故障可能是由于提供程序的问题,或者是一些意外的Graph节点错误。当发生非确定性故障时,Graph节点将重试失败的处理程序,并随着时间的推移而后退。

在某些情况下,索引人可能会解决故障(例如,如果错误是由于没有正确类型的提供程序导致的,则添加所需的提供程序将允许继续索引)。然而,在其他情况下,需要更改子图代码。

确定性故障被视为“最终”,并为故障区块生成索引证明,而非确定性故障则不是,因为子图可能会“可靠”并继续索引。在某些情况下,非确定性标签是不正确的,子图永远无法克服错误;此类故障应报告为Graph节点存储库中的问题。

区块和调用缓存

链到本节

Graph节点在存储中缓存某些数据,以保存来自提供程序的重新绘制。区块被缓存,eth_calls的结果也被缓存(后者作为特定区块被缓存)。这种缓存可以在稍微改变的子图的“重新同步”期间显著提高索引速度。

然而,在某些情况下,如果以太坊节点在一段时间内提供了错误的数据,这可能会进入缓存,导致错误的数据或失败子图。在这种情况下,索引人可以使用graphman清除不良的缓存,倒回受影响的子图,然后从(希望)健康提供程序获取新数据。

如果怀疑区块缓存不一致,例如tx收据丢失事件:

  1. graphman链列表以查找链名称。
  2. graphman chain check-blocks <CHAIN> by-number <NUMBER> 将检查缓存的块是否与提供程序匹配,如果不匹配,则从缓存中删除该块。
    1. 如果存在差异,则使用graphman chain truncate <CHAIN>截断整个缓存可能更安全。
    2. 如果区块与提供程序匹配,则可以直接针对提供程序调试问题。

查询问题和错误

链到本节

一旦子图被索引,索引人就可以期望通过子图的专用查询端点来服务查询。如果索引人希望为大量查询量提供服务,建议使用专用查询节点,如果查询量非常大,索引人可能需要配置副本分片,以便查询不会影响索引过程。

然而,即使使用专用的查询节点和副本,某些查询也可能需要很长时间才能执行,在某些情况下还会增加内存使用量,并对其他用户的查询时间产生负面影响。

没有一个"万灵丹",而是一系列用于预防、诊断和处理慢速查询的工具。

查询缓存
链到本节

默认情况下,Graph 节点缓存GraphQL查询,这可以显著减少数据库负载。这可以进一步使用GRAPH_QUERY_CACHE_BLOCKSGRAPH_QUERY_CACHE-MAX_MEM设置进行配置-请在此处阅读更多信息。

分析查询
链到本节

有问题的查询通常以两种方式之一出现。在某些情况下,用户自己报告给定的查询很慢。在这种情况下,挑战是诊断缓慢的原因——无论是一般问题,还是特定于子图或查询。如果可能的话,当然要解决它。

在其他情况下,触发因素可能是查询节点上的高内存使用率,在这种情况下,首要挑战是要确定导致问题的查询。

索引器可以使用qlog来处理和汇总Grap​​h Node的查询日志。 GRAPH_LOG_QUERY_TIMING 也可以启用以帮助识别和调试慢速查询

针对慢查询,索引器有几个选项。当然,他们可以改变成本模型,显著增加发送有问题查询的成本。这可能导致该查询的频率降低。然而,这通常并不能解决问题的根本原因。

账户式优化
链到本节

存储实体的数据库表通常有两种类型:“类交易”,即实体一旦创建,就永远不会更新,即存储类似于金融交易列表的内容;“类账户”,即经常更新实体,即存储每次记录交易时都会修改的类似金融账户的内容。类账户表的特点是,它们包含大量实体版本,但不同的实体相对较少。通常,在这种表中,不同实体的数量是行总数的1%(实体版本)。

对于类似账户的表,graph-node 可以生成查询,利用Postgres如何以如此高的变化率存储数据的细节,即最近区块的所有版本都位于此类表的总存储的一小部分中。

命令graphman stats show <sgdNNNN> 显示部署中每个实体类型/表的不同实体数量以及每个表包含的实体版本。该数据基于Postgres的内部估计,因此必然是不精确的,可能会偏离一个数量级。entity列中的-1 表示Postgres认为所有行都包含一个不同的实体。

通常,不同实体的数量小于行/实体版本总数的1%的表是类似账户的优化的好候选表。当graphman stats show的输出表明表可能从该优化中受益时,运行graphman stats show <sgdNNN> <table>将执行表的完整计数-这可能会很慢,但可以精确测量不同实体与整体实体版本的比率。

一旦一个表被确定为类似账户,运行graphman stats account-like <sgdNNN> <table> 将为针对该表的查询启用类似账户的优化。可以使用graphman stats account-like --clear <sgdNNN><table>)再次关闭优化查询节点,最多需要5分钟才能注意到优化已打开或关闭。打开优化后,需要验证更改实际上不会使该表的查询变慢。如果您已经将Grafana配置为监视Postgres,那么在pg_stat_activity中会出现大量缓慢的查询,需要几秒钟。在这种情况下,需要再次关闭优化。

对于类似Uniswap的子图,pairtoken表是这种优化的主要候选项,并且可以对数据库负载产生显著影响。

删除子图

链到本节

这是一项新功能,将在Graph Node 0.29.x中提供。

在某个时刻,索引人可能想要删除给定的子图。这可以通过删除部署及其所有索引数据的graphman drop, 轻松完成。部署可以被指定为子图名称、IPFS has、Qm..,或数据库命名空间sgdNNN此处提供了更多文档。

编辑

上页
Overview
下页
Firehose
编辑