rpcpool.solana_rpc

Solana RPC 角色

这是一个用于部署 Solana RPC 节点的 Ansible 角色。它配置了在 solana 用户下运行的 RPC 模式的验证器软件。RPC 服务作为用户服务安装,运行在同一个用户下。

更新

  • 从 Solana 1.8.15(主网)和 1.9.6(测试网)起,您需要指定 solana_full_rpc_api: true,以使此角色能够创建完全暴露的 RPC API 节点。

硬件要求

一个 RPC 服务器至少需要与 Solana 验证器相同的规格,但通常需求更高。特别是,我们建议使用 256 GB 的 RAM 来存储索引。有关硬件要求的更多信息,请查看 https://docs.solana.com/running-validator/validator-reqs。我们强烈建议您使用物理服务器提供商(而不是 Hetzner),而不是云提供商,除非您知道自己在做什么(如果是这样,您为什么还在看这个页面呢?)。

在部署之前,您应该准备主机,以便用于账户数据库和账本位置的目录被正确配置。这可能包括为账户设置 tmpfs 文件夹以及为账本设置单独的文件系统(理想情况下在 NVME 驱动器上)。配置的一种常见方法可能是:

/solana/tmpfs - 一个 100 GB 的 tmpfs 分区来保存账户状态
/solana/ledger - 一个 2 TB 的 NVME 驱动器来保存账本

为什么选择物理服务器而不是云?

云服务器(如 AWS、GCP 等)一般不适合 Solana,原因如下:

  1. 外部流量费用非常高,而 Solana 将大量使用外部流量。
  2. 单核性能通常太低,无法像物理服务器那样提升。
  3. 许多云提供商不希望在其低成本实例上运行 Solana 的工作负载,导致您不得不使用非常昂贵的物理实例。

为什么不选择 Hetzner?

Hetzner 已决定不希望 Solana RPC 服务在其网络上运行。他们主动阻挡与 Solana 入口点的连接,并限制任何 Solana 流量的速度。您的 Solana 节点不仅难以跟上网络(在主网上可能永远无法赶上),而且 Hetzner 很可能会关闭您的帐户。

软件要求

  • Ansible >= 2.7(主要在 Ansible 2.8 上测试)
  • 目标部署机器上的 Ubuntu 18.04 及以上版本

该角色假设您对 Solana 验证器软件的部署过程有一定的了解。

角色变量

部署确保您下载的 solana-installer 版本的校验和与 vars/main.yml 中给出的值匹配。如果您想安装未列出的 Solana 版本,最好先下载并检查 solana-installer 脚本的 sha256 校验和(https://raw.githubusercontent.com/solana-labs/solana/master/install/solana-install-init.sh)。

Solana 有很多可配置参数。许多参数都有可用的默认值,您可以使用此角色在不更改默认值的情况下部署 Solana RPC 节点,您应该能够获得不错的体验。如果您在没有指定任何参数的情况下运行此角色,它将配置一个标准的 mainnet RPC 节点。

基本变量

这些是配置验证器设置的基本变量。它们有默认值,但您可能希望根据您的设置进行自定义。

名称 默认值 描述
solana_version stable 要安装的 Solana 版本。
solana_full_rpc_api true 是否启用完全的 RPC API。通常这是您想要的。
solana_root /solana Solana 账本和账户的主目录
solana_ledger_location /solana/ledger Solana 账本的存储位置(应在 NVME 上)
solana_accounts_location /solana/ledger/accounts 存储 Solana 账户信息的位置。如果您使用 tmpfs 存储账户,这应该是 tmpfs 挂载点的子目录(例如,如果 tmpfs 挂载在 /solana/tmpfs,则为 /solana/tmpfs/accounts
solana_snapshots_location 存储 Solana 快照的位置。最好将其放在与账本不同的 NVME 上。
solana_keypairs [] 要复制到验证器节点的密钥对列表。列表中的每个条目应具有 keyname 条目。这将创建 /home/solana/<name>.json,包含 key 的值。
solana_generate_keypair true 是否生成密钥对。如果您没有指定 solana_keypairs,并将此设置为 true,则将生成一个新密钥并放置在 /home/solana/identity.json
solana_public_key /home/solana/identity.json 验证器节点的身份位置。
solana_network mainnet 此节点应该所属的 Solana 网络
solana_environment 参见 defaults/main.yml 要为验证器节点指定的环境变量,最重要的是 RUST_LOG
solana_enabled_services [ solana-rpc ] 启动时自动启动的服务列表
solana_disabled_services [ ] 要设置为禁用的服务列表

端口

以下端口需要为您的 RPC 服务器配置。

名称 默认值 描述
solana_gossip_port 8001 用于 gossip 流量的端口(需要在防火墙中公开开放 TCP 和 UDP)
solana_rpc_port 8899 (+8900) 接收 RPC (和 websocket)的端口。通常仅在本地主机上打开。在这些端口前放置一个代理,如 haproxy,并不要公开开放。
solana_rpc_bind_address 127.0.0.1 绑定 RPC 的地址。通常应该是本地主机。在其前放置一个代理,如 haproxy,以接受公共流量
solana_dynamic_port_range 8002-8020 用于接收 Solana 流量的端口。可能需要在防火墙中公开开放 UDP。

从这个列表中,您可以了解默认情况下需要在防火墙中开放至少 8001-8020 端口。

对于纯 RPC 节点,可能可以关闭 TPU 和 TPU 转发端口。这些端口是动态分配的,您可以通过在 solana gossip 中查看节点来看到它们。如果您想在防火墙中过滤它们,可以使用这个工具:https://github.com/rpcpool/tpu-traffic-classifier。使用此工具可以通过运行以下命令在本地节点上阻止传入的 TPU 和 TPU 转发:

./tpu-traffic-classifier -config-file config.yml -our-localhost -tpu-policy DROP -fwd-policy DROP -update=false

将其放入 SystemD 服务中,您可以在节点启动时运行,并保持其持续运行。

网络特定变量

这些变量的默认值在 vars/{{ solana_network }}-default.yml 中指定(例如 vars/mainnet-default.yml)。您也可以通过提供文件 {{ solana_network }}.yml 来指定自己的值。您需要指定所有这些变量,除非您依赖于默认值。

名称 默认值 描述
solana_network mainnet 此节点应加入的 Solana 网络
solana_metrics_config 见 vars/mainnet-default.yml 指标端点
solana_genesis_hash 见 vars/mainnet-default.yml 此网络的创世纪哈希
solana_entrypoints 见 vars/mainnet-default.yml 入口点主机
solana_known_validators 见 vars/mainnet-default.yml 启动时获取快照和创世纪 bin 的已知验证器
solana_expected_bank_hash 见 vars/mainnet-default.yml 预期的银行哈希
solana_expected_shred_version 见 vars/mainnet-default.yml 预期的 shred 版本
solana_index_exclude_keys 见 vars/mainnet-default.yml 由于性能原因要从索引中排除的键

RPC 特定变量

名称 默认值 描述
solana_rpc_faucet_address 指定一个 RPC 水龙头
solana_rpc_history true 是否提供 RPC 的历史值
solana_account_index program-id spl-token-owner spl-token-mint 启用哪些索引。这会极大提高性能,但会延长启动时间并可能增加内存需求。

性能变量

这些变量可以调节以提高性能。

名称 默认值 描述
solana_snapshot_compression 是否压缩快照。指定 none 以提高性能。
solana_snapshot_interval_slots 多长时间采取快照。增加以提高性能。建议值为 500。
solana_pubsub_max_connections 1000 允许的最大 pubsub 连接数。
solana_bpf_jit 是否启用 BPF JIT。默认在开发网启用。
solana_banking_threads 16 银行线程的数量。
solana_rpc_threads RPC 线程的数量(系统上默认的最大线程/核心数量)
solana_limit_ledger_size solana 默认,250 百万 本地账本存储的大小。对于一个完整的纪元,设置在 350 百万到 500 百万之间的值。为最佳性能设置在 50(最小值)。
solana_accounts_db_caching 是否启用账户数据库缓存
solana_accounts_shrink_path 您可能希望为账户缩减处理过程指定另一个位置

Bigtable

您可以指定 Google Bigtable 账户凭证,以查询本地账本中不存在的块。

名称 默认值 描述
solana_bigtable_enabled false 启用 bigtable 访问
solana_bigtable_upload_enabled false 启用 bigtable 上传(下面提供的凭证需要写入访问权限)
solana_bigtable_project_id Bigtable 项目 ID
solana_bigtable_private_key_id Bigtable 私钥 ID
solana_bigtable_private_key Bigtable 私钥
solana_bigtable_client_email Bigtable 客户端邮箱
solana_bigtable_client_id Bigtable 客户端 ID
solana_bigtable_client_x509_cert_url Bigtable 证书 URL

有关 BigTable 的更多信息,请参见 https://github.com/solana-labs/solana-bigtable

处理分叉

偶尔,开发网/测试网会经历分叉。在这些情况下,请按照 Discord 中的指示使用以下参数:

名称 默认值 描述
solana_hard_fork 硬分叉
solana_wait_for_supermajority 节点是否应等待超级多数

CPU 调节器和 Sysctl 设置

您需要进行某些配置,以使 RPC 节点正常运行。此角色可以帮助您进行一些标准配置更改。但是,完全优化在很大程度上取决于硬件,因此您需要花时间了解如何正确配置硬件。

但是,优化的最重要因素是 CPU 性能调节器。它控制提升行为和能耗。在许多数据中心的主机中,通常是在性能和能耗之间取得平衡。针对 Solana,我们真的需要它们以最快的速度运行。要设置服务器的 CPU 调节器,有三个选项:

  1. 您可以访问 BIOS 并将 BIOS CPU 设置为 max performance。这似乎在 HPE 系统上效果很好。在这种情况下,请将变量指定为 cpu_governor: bios。这在某些情况下也需要针对 AMD EPYC 系统进行设置。
  2. 您可以访问 BIOS,并将 BIOS CPU 设置为 os control。这应该是典型的默认值。在这种情况下,您可以将 cpu_governor 变量保留为默认值,或明确设置为 cpu_governor: performance
  3. 如果您无法访问 BIOS 或 CPU 调节器设置。如果可能,尽量将其设置为 cpu_governor: performance。否则,希望您的提供商已将其配置为良好性能!

您需要进行的第二个配置是编辑各种内核参数,以适应 Solana RPC 使用案例。

一种选择是与此配置一起部署 solana-sys-tuner,以为您自动调整一些变量。

另一个选择是,特别是如果您是性能调优的新手,使用来自 RedHat 的 tunedtune-adm,其中 throughput-performance 配置文件非常合适。

最后,如果您通过此角色进行部署,还可以为本剧本指定一系列 sysctl 值,以便在主机上自动设置。这提供了完全的控制,并将其配置为永久配置。 以下是我们在 rpcpool 上使用的 sysctl 值列表:

sysctl_optimisations:
  vm.max_map_count: 700000
  kernel.nmi_watchdog: 0
# CPU 绑定任务的最小抢占粒度:
# (默认:1 毫秒# (1 + ilog(ncpus)),单位:纳秒)
  kernel.sched_min_granularity_ns: '10000000'
# SCHED_OTHER 唤醒粒度。
# (默认:1 毫秒# (1 + ilog(ncpus)),单位:纳秒)
  kernel.sched_wakeup_granularity_ns:  '15000000' 
  vm.swappiness: '30'
  kernel.hung_task_timeout_secs: 600
# 这意味着将更少地收集虚拟内存统计信息,但对于降低延迟是一个合理的折衷
  vm.stat_interval: 10
  vm.dirty_ratio: 40
  vm.dirty_background_ratio: 10
  vm.dirty_expire_centisecs: 36000
  vm.dirty_writeback_centisecs: 3000
  vm.dirtytime_expire_seconds: 43200
  kernel.timer_migration: 0
# pid_max 的建议值是 1024 * <系统中 CPU 核心/线程的数量>
  kernel.pid_max: 65536
  net.ipv4.tcp_fastopen: 3
# 来自 solana systuner
# 参考:https://medium.com/@CameronSparr/increase-os-udp-buffers-to-improve-performance-51d167bb1360
  net.core.rmem_max: 134217728
  net.core.rmem_default: 134217728
  net.core.wmem_max: 134217728
  net.core.wmem_default: 134217728

示例剧本

主网节点:

    - hosts: rpc_nodes
      become: true
      become_method: sudo
      roles:
         - { role: rpcpool.solana-rpc, solana_network: mainnet }

测试网节点:

    - hosts: rpc_nodes
      become: true
      become_method: sudo
      roles:
         - { role: rpcpool.solana-rpc, solana_network: testnet }

开发网节点:

    - hosts: rpc_nodes
      become: true
      become_method: sudo
      roles:
         - { role: rpcpool.solana-rpc, solana_network: devnet }

启动 RPC 节点

部署后,您可以登录到机器并运行 su -l solana 成为 solana 用户。

要查看在部署过程中为您生成的 Solana 验证器命令行,您可以查看 /home/solana/bin/solana-rpc.sh。请记住,您对该文件的任何更改将在下一次运行此 Ansible 时被覆盖。

在第一次启动时,您应该注释掉文件 /home/solana/bin/solana-rpc.sh 中的 --no-genesis-fetch--no-snapshot-fetch。这将允许 Solana 下载首次启动所需的基本文件。在第一次启动验证器后,请记得再次激活这些行。

然后,通过运行 systemctl --user start solana-rpc 启动 Solana RPC 进程。您可以通过运行 systemctl --user status solana-rpc 查看进程的状态。第一次启动需要一些时间。您可以通过运行 solana catchup --our-localhost 监视启动。

最后,要查看 Solana RPC 节点的日志,请运行 journalctl --user -u solana-rpc -f

如果这是您第一次运行 Solana 节点,您可以在 https://docs.solana.com/running-validator/validator-starthttps://github.com/agjell/sol-tutorials/ 上找到有关如何操作节点的更多详细信息。

检查 RPC 节点

在您验证节点已启动后,基本检查是跟踪 catchup:

solana catchup --our-localhost

之后,您可以继续检查它是否正确处理 RPC 调用。

测试 RPC 访问

您还可以尝试几个简单的验证命令(感谢 buffalu: https://gist.github.com/buffalu/db6458d4f6a0b70ac303027b61a636af):

curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
  {"jsonrpc":"2.0","id":1, "method":"getSlot", "params": [
      {
        "commitment": "processed"
      }
    ]}
'

curl http://localhost:8899  -X POST -H "Content-Type: application/json" -d '
  {"jsonrpc":"2.0","id":1, "method":"getSlot"}
'

测试 WebSocket 访问

测试 WebSockets 的最简单方法是安装实用程序 wscat。要这样做,您需要安装 NodeJS 和 NPM,然后运行 npm install wscat

然后,您可以通过以下方式连接到您的 WebSocket:

wscat -c localhost:8900

从那里,您将获得一个命令提示符,您可以在其中手动输入 WebSocket 订阅请求:

> {"jsonrpc":"2.0", "id":1, "method":"slotSubscribe"}

您现在应开始接收来自 RPC 节点的插槽确认的定期更新。

RPC 节点落后/未能赶上

RPC 节点最常见的性能问题是它不断落后于网络,无法赶上。

如果它在您第一次启动时无法赶上,这通常是由于配置错误。最常见的问题是您的 CPU 提升频率(有关 CPU 配置的更多详细信息,请参见上文):

  • 检查您的 CPU 是否足够新(任何 < EPYC 第二代的 AMD 或 < Cascade Lake 的 Intel 都会感到挣扎)
  • 检查您的 CPU 调节器在 BIOS 和内核设置中是否未设置为节能模式
  • 使用 watch -n 1 grep MHz /proc/cpuinfo 观察 CPU 频率,通常需要所有核心的频率 > 3GHz(经验法则)。您 不应 看到任何核心降到 1.4-1.8。

如果它曾经能够赶上但现在无法(或者修复 CPU 并没有解决):

  • 检查内存/CPU/网络 - 您是否有良好的 CPU 频率,是否在交换区中下降(内存不足)或提供商是否限制 UDP 包?
    • _CPU_:修复性能调节器/提升设置,获取更新一代的 CPU 或更好的全核涡轮(查看 wikichip 获取详细信息)。请记住,不同一代的 MHz 不一样。Broadwell 3.0 GHz 不等于 Cascade Lake 3.0 GHz 或 EPYC 第三代 3.0 GHz。
    • _网络_:检查 UDP 包的限制和连通性。您需要至少 500 Mbps 的通道,并且没有任何对 UDP 的限制。有些提供商喜欢阻止 UDP 或为了 DDoS 保护而减少其速度。这适用于进出。如果您的节点在接收时受到限制,它将无法及时从网络接收碎片。检查您的防火墙,确保没有。
    • _内存_:增加 RAM。Solana 不喜欢在交换上运行,因此如果您经常进入交换,则需要解决这个问题。一种临时解决方案可能是禁用 spl-token-owner / spl-token-mint 索引。它们已经变得非常大。
    • _磁盘_:检查存储账本和/或账户的 NVME 是否损坏。简单的 dmesg 或 SMART 状态查询应该可以告诉您。
  • 有一个错误,在通过 RPC 进行大量获取块调用后,节点会持续落后,尝试重启节点,如果那样有帮助,那么这可能就是您的问题。
  • 您是否尝试过拔掉它,然后再插回去?有时清理您的账本并重启可能会有所帮助。
  • 检查您的流量模式。某些 RPC 流量模式可以 轻易 使您的节点滞后。也许您需要添加另一个节点并分流 RPC 流量,或者您需要对像 getProgramAccounts 这样的有问题查询进行流量限制。

访问历史数据

默认情况下,当您启动 RPC 节点时,它将开始从通过 Solana 网络接收的区块构建其本地账本。此本地账本从您节点启动时下载的账户快照点开始。如果您没有在 solana-validator 命令行中添加 --no-snapshot-fetch,则验证器在启动时通常会从网络中拉取快照。这将导致您的账本中在您停止 RPC 节点与其下载账户快照之间留下孔或缺口。为了避免这种情况,请在第一次启动节点后始终指定 --no-snapshot-fetch。请记住,每次拉取快照时,都会在本地账本中创建一个孔。

本地账本的大小由参数 --limit-ledger-size 决定,单位为碎片。碎片是固定的数据单元。碎片与区块之间的转换不是固定的,因为区块可以具有不同的大小。因此,很难说您的节点将存储多长时间或多少个区块的历史数据。您需要根据需要进行调优。一个好的起点可以是 2.5-3.5 亿碎片,这应该大约覆盖一纪元,而这应该意味着大约 3 天。

RPC 节点存储的数据的确切数量还取决于参数 --enable-cpi-and-log-storage--enable-rpc-transaction-history。这些参数对节点保留和提供完整的区块和交易数据是必要的。

您的节点只能提供存储在其本地账本中的数据。这意味着您的历史记录将始终从您启动节点时开始(实际上是:您启动节点的快照插槽)。如果网络当前在插槽 N,而您在插槽 M 拉取了快照,则您的节点将开始重建其在插槽 M 和插槽 N 之间的历史记录。这就是 catchup 期间发生的事情,节点正在处理(重播)发生在M和N之间的所有事情,直到它赶上网络并处理所有当前的传入数据。

在理论上,节点可以存储尽可能多的历史记录,前提是您能将其放入高速存储中(例如,如果您 /没有/ 指定 --limit-ledger-size 或给了一个巨大的值)。但是,这并不扩展到创世纪。要获取所有历史数据,您可以使用内置的 Google BigTable 支持。您可以设置节点将数据上传到 Google BigTable 实例,以便可以永久供历史查询使用。您也可以配置节点以支持对 BigTable 实例的查询。在这种情况下,对于节点本地账本中没有的任何查询,它将向 Google BigTable 发出请求,如果在 Google BigTable 中找到数据,它可以从那里提取数据。

一些 RPC 提供商和 Solana 基金会拥有可以追溯到创世纪的 BigTable 副本。有关此事的更多信息,请参见 https://github.com/solana-labs/solana-bigtable

索引与性能:或者,为什么我的 RPC 这么慢?

Solana 验证器生成三个索引 program-idspl-token-mintspl-token-owner。后两个用于支持通过 getTokensByOwnergetTokenLargestAccounts 或通过 getTokensByDelegate 的查询。

这些索引开始变得非常庞大。如果您不需要这些查询以便于您的 RPC 节点,那么您应该将它们删除,因为这将显着减少节点的内存使用并提高启动时间。

如果您确实需要这些 RPC 调用,那么您确实需要通过账户索引标志激活索引,否则这些调用将会极其缓慢。这样需要大量的 RAM - 通常我们不建议在可用 RAM 少于 512 GB 的情况下部署这些。

一种替代方法可能是使用 Geyser 插件,如 Postgres 插件,可以帮助加快查询速度而无需依赖内存中的索引:https://github.com/rpcpool/solana-geyser-park。

安全问题

安全是一个广泛的领域,您无法依赖 GitHub 库中的小指南。通常,至少您 应该 确保您的 RPC 服务器不会直接暴露 8899 和 8900 端口,而没有任何反向代理和访问控制在其前面。实现此目的的简单方法是使用 nginx 或 HAproxy 作为反向代理。您可以通过各自的内置工具添加 SSL 支持和身份验证。

为了安全起见,您可以确保您的 rpc-bind-address 设置为 127.0.0.1(这是此角色的默认值),以便它仅响应本地请求。

其他剧本

通常,您会想在 Solana RPC 前面部署一个反向代理。HAproxy 是一个很好的选择,我们为 solana rpc 服务器的 HAproxy 配置提供了一个剧本 这里

其他指南和文档

以下是有关 Solana RPC 的一些其他指南、资源和文档:

我们对这些文档的准确性或质量不作任何声明。请审查并自行决定要遵循哪些文档!

许可证

MIT

作者信息

此角色最初由 Triton One 开发。欢迎提出补丁、建议和改进。

关于项目

Ansible role for deploying Solana RPC nodes

安装
ansible-galaxy install rpcpool.solana_rpc
许可证
mit
下载
137
拥有者
Providers of Solana RPC services