简而言之:轮询是一种基于拉取的模式,应用程序会以固定间隔反复向区块链节点查询新数据。流式传输是一种基于推送的模式,新数据在链上生成后会自动传递给应用程序。轮询虽然实现简单,但会浪费资源、引入延迟,且存在数据丢失的风险。流式传输在规模化应用时效率更高、速度更快、更可靠,但需要不同的基础设施。 对于大多数生产环境中的区块链应用程序而言,流式传输是更优的数据采集方案。
简明解释
每个区块链应用都需要知道链上何时发生某些事件。钱包需要知道用户何时收到转账;DeFi 协议需要检测价格预言机何时更新;交易机器人需要在新的交易进入区块的瞬间就检测到它们;分析平台需要对每个区块在生成时立即进行处理。问题在于,你的应用如何获知这些事件。
在轮询模式下,您的应用程序会运行一个循环:调用 RPCendpoint ,检查是否有新情况发生,处理任何新数据,等待固定时间间隔,然后重复上述步骤。这是大多数开发者最早接触的模式,因为它与 HTTP API 的工作原理自然契合。设置一个定时器,每 N 秒发送一次请求,处理响应。除了能够发送 HTTP 请求外,它不需要任何特殊的基础设施。
在流式处理中,您的应用程序只需建立一次连接或配置一次数据管道,新数据就会自动到达。无需循环、无需定时器、也无需重复请求。当生成新的数据块时,数据会自动流向您的应用程序,而无需应用程序主动请求。应用程序的任务仅仅是处理随数据到达而传入的数据。
民意调查在实践中是如何运作的
一种用于监控新区块的典型轮询实现方式如下:您的应用程序调用“eth_blockNumber”获取最新区块,将其与上次处理的区块进行比较,通过“eth_getBlockByNumber”获取任何新区块,提取所需数据,并安排下一次轮询。 每次迭代至少需要一次 RPC 调用(用于检查最新区块号),并且可能还需要更多次调用(用于获取每个新区块的完整区块数据、交易收据和事件日志)。
轮询间隔是一个关键的设计决策。如果轮询过于频繁,就会在答案明明是“没有”的情况下,仍通过RPC请求(以及信用点)来询问“有什么新内容吗?”,从而造成资源浪费。以Ethereum 为例,该节点每12秒生成一个区块,如果每秒进行一次轮询,意味着12次请求中有11次都无法获得有用的信息。 如果轮询间隔过长,则会引入延迟。如果间隔为 30 秒,你可能要等到新区块生成 30 秒后才能发现它。此外,每个间隔内可能需要处理多个区块,从而导致系统负载不均衡。
轮询会带来若干可靠性风险。如果轮询因网络错误、速率限制或节点问题而失败,除非您的应用程序记录了上次处理的区块编号,并在下次成功轮询时回溯至该位置,否则可能会完全遗漏该区块。 如果应用程序崩溃或重启,它必须确定中断的位置并从该点恢复,同时处理停机期间生成的所有区块。如果轮询工作进程因处理延迟而落后,区块链末端与应用程序状态之间的差距就会扩大,而要赶上进度则需要处理积压的区块。
在高吞吐量的区块链上,轮询会变得尤为棘手。Solana 每 400 毫秒生成一个槽位。Arbitrum 和Base 每 250 毫秒生成一个区块。若以这些区块链的区块生成速率对其进行轮询,仅检查区块编号就需要每秒 2 到 4 次 RPC 请求,此外还需额外请求完整的区块数据。当扩展到多条区块链时,RPC 请求量(及成本)会随着区块链数量及其各自的区块生成速率呈线性增长。
流媒体在实际中的工作原理
WebSocket 订阅是区块链流式传输最简单的一种形式。您的应用程序会与一个节点建立持久的 WebSocket 连接,并发送订阅请求(例如带有“newHeads”参数的“eth_subscribe”)。节点会在每个新区块头生成后,立即通过该开放连接将其推送至您的应用程序。无需轮询,没有多余的请求,也没有延迟差距。
WebSockets 适用于简单用例,但在大规模场景下存在显著局限。连接是有状态的,可能会因网络问题、服务器重启或空闲超时而中断。当连接中断时,您的应用程序将无法获取重新连接前发生的任何事件,并且必须检测到断开连接、重新连接并补全数据缺口。在多个链上管理多个并发 WebSocket 连接会增加复杂性。 此外,WebSocket 订阅也不支持历史数据。如果您需要处理上周的区块,WebSocket 无法提供帮助。
专为流式传输设计的流服务解决了这些限制。您的应用程序无需维护易中断的 WebSocket 连接,而是配置一条由流服务端到端管理的数据管道。该服务连接到区块链节点,处理每个区块,应用您的过滤器,并将结果以保证送达的方式传输到您的目标位置。如果目标位置暂时不可用,该服务会缓冲数据并重试。如果发生重组,该服务会发送更正数据包。 如果您需要历史数据,同一条数据管道可以从任意起始区块开始补填数据。
两种方法的比较
延迟是最明显的差异。在最佳情况下,轮询的延迟始终等于轮询间隔;但在实际应用中,由于处理时间和错误恢复等因素,延迟通常会更长。流式传输则会在数据一经生成即刻发送,通常在数据块生成后的几秒内即可完成。对于交易机器人或实时仪表盘等对延迟敏感的应用程序,流式传输的速度明显更快。
资源效率是第二个主要区别。轮询生成的请求量与轮询频率成正比,无论是否存在新数据。一个每秒检查新区块的轮询 worker,即使它只关注一个每周触发一次的特定事件,每天也会发出 86,400 次请求。流式处理消耗的资源与实际数据量成正比。如果没有发生任何符合过滤条件的事件,则不会发送任何数据,您这边也不会消耗任何资源。
在规模化应用中,可靠性是区分这两种方法的关键。轮询方式要求您的应用程序自行维护状态跟踪、缺失检测、错误恢复和补发逻辑。每个边界情况(如数据块丢失、重复处理、重组、速率限制、节点故障转移)都必须在您的代码中进行处理。流式服务则在提供商端处理这些边界情况,提供无缺失、有序且去重的数据流,您的应用程序可以处理这些数据流,而无需担心基础设施的可靠性。
复杂性是需要权衡的。轮询在初期更易于实现。 一个基本的轮询循环只需20行代码即可编写。但这种简单性具有欺骗性,因为经过生产环境验证的轮询需要错误处理、退避逻辑、状态管理、重组织检测以及监控,这些内容可能会使代码量激增至数百行。流式传输需要预先配置数据管道和能够接收推送数据的目标系统(如Webhook服务器或具有适当摄取逻辑的数据库),但一旦配置完成,其后续维护工作量要少得多。
轮询和流式传输有什么区别?
轮询和流式传输解决的是同一个问题,即把最新的链上数据引入到你的应用程序中,但两者的控制权关系恰好相反flow 。在轮询模式下,你的代码是主动方:它会反复调用RPCendpoint并询问是否有任何变化。而在流式传输模式下,提供方是主动方,会在每个新区块或匹配事件生成后立即将其推送给你。下表从生产环境中最重要的几个维度对这两种模式进行了比较。
维度 | 民意调查 | 流媒体 |
|---|---|---|
数据flow | 基于拉取模式,您的应用会主动请求数据 | 基于推送,数据会自动发送 |
延迟 | 等于或长于抽样间隔 | 块生产开始后的几秒内 |
资源使用情况 | 与轮询频率成正比,即使在空闲状态下也是如此 | 与实际数据量成正比 |
如何选择轮询间隔?
如果进行轮询,轮询间隔应与所读取区块链的区块生成时间保持一致。如果轮询频率远高于区块生成速度,不仅会浪费请求,还可能触发速率限制;而如果轮询频率远低于区块生成时间,则会增加本可避免的延迟,并迫使工作节点同时处理多个区块。下表列出了各网络的典型区块生成时间及其对轮询实践的影响。
区块链 | 大致区块时间 | 民意调查的启示 |
|---|---|---|
Bitcoin | 大约10分钟 | 1到2分钟的间隔已经绰绰有余了 |
Ethereum | 大约12秒 | 每4至12秒进行一次轮询,既能保持数据最新,又不会造成资源浪费 |
BNB Smart Chain | 大约3秒 | 子块轮询会增加负载,但收益甚微 |
在什么情况下仍应使用轮询?
对于大多数生产工作负载而言,流式处理是更好的默认选择,但在某些情况下,轮询仍然是一个合理的选择。 一次性脚本、补录任务和不常运行的批处理作业,通常无需采用托管管道。当您仅需按需获取单个值时,例如在用户执行操作前查询余额——此时没有可订阅的连续数据流——轮询也是可行的。不过,当数据时效性和数据量确实重要时,权衡取舍的界限会迅速变化,因此在确定具体方案之前,了解实时数据与历史数据之间的区别会很有帮助。
流式处理如何处理数据重组和数据丢失?
处理实时区块链数据最困难的部分并非正常流程,而是边界情况。链重组可能会替换掉应用程序已经处理过的区块,而连接中断则可能导致数据出现缺口。如果使用原始轮询或 WebSockets,您必须自行检测并修复这些情况。像 Quicknode Streams 这类托管服务会为你处理这些问题:它按最终性顺序交付数据,在发生链重组时发出更正负载,并在目标不可用时进行缓冲和重试。正是这种差异,使得基于推送的交付在规模化运营时要容易得多。
常见问题解答
流媒体是否总是比民意调查更好?
并非总是如此。对于大多数需要持续、低延迟数据的生产应用而言,流式传输在效率和可靠性方面更具优势。但对于一次性脚本、简单的余额查询或低频任务,轮询方式完全足够,且更易于配置。正确的选择取决于数据必须有多及时,以及处理的数据量有多大。有关推送式模型的入门指南,请参阅“什么是区块链数据流式传输”。
我应该多久轮询一次 RPCendpoint ?
请将轮询间隔与区块链的区块生成时间相匹配。在Ethereum 上,每 4 到 12 秒轮询一次既能保持数据最新,又不会浪费请求。在Solana 或Base 这样的高速区块链上,按区块生成频率进行轮询并不现实,流式处理更为合适。如果轮询频率远高于区块生成频率,通常不会返回新数据,反而会消耗请求配额。请参阅RPC 请求的工作原理,了解每次调用涉及的内容。
轮询的成本是否高于流式传输?
在大规模场景下确实如此。轮询会按照固定时间表生成请求,无论是否有新数据,因此一个繁忙的轮询工作进程每天可能发起数万次调用,却只捕获到寥寥几个事件。流处理消耗的资源与实际符合过滤条件的數據量成正比,这通常意味着更少的无效请求,从而降低了持续性工作负载的成本。
在重组过程中,我的数据会发生什么变化?
如果仅使用简单的轮询或原始 WebSockets,重组织可能会导致您的应用程序保留一些在规范链上已不存在的交易。托管流式服务能够检测到重组织,并发送更正数据包,从而确保您的状态保持一致。理解吞吐量与延迟之间的权衡,也有助于您决定在将数据视为已结算之前应等待多长时间。
我能从流媒体服务中获取历史数据吗?
是的。与 WebSocket 订阅不同——WebSocket 订阅仅从连接时刻起传递新事件——完整的流式处理管道可以使用相同的配置,从过去的任意时间点开始补发数据。这使您能够回放历史数据,然后无缝过渡到实时数据,而无需运行两个独立的系统。
Quicknode 是如何同时支持这两种模式的
Quicknode其核心 API在所有受支持的区块链上均支持通过 HTTP RPC 端点进行轮询,以及通过 WebSocket 连接进行实时订阅。对于使用轮询的应用程序,Quicknode 关于高效 RPC 请求的指南介绍了如何最大限度减少无效调用、实现正确的错误处理以及管理速率限制的最佳实践。
对于希望摆脱轮询机制的应用程序,Quicknode (Streams )提供了一条完全托管的数据流管道。Streams 可提供实时区块链数据,具备交付保证、最终性排序处理、自动重组处理以及服务器端过滤功能,且无需您的应用程序维护 WebSocket 连接或轮询基础设施。Streams 支持将数据传输至webhooks 、PostgreSQL、Snowflake、Amazon S3、Azure Storage 等平台,使其能够适应任何后端架构。Quicknode的文档中提供了 WebSocket 订阅与Streams 之间的直接对比指南,涵盖了从轮询或基于 WebSocket 的架构进行迁移时需要考虑的权衡因素和迁移路径。
延伸阅读
什么是 RPCendpoint ?-Quicknode 术语表
RPC 请求是如何工作的?-Quicknode 术语表
WebSocket 与Quicknode 的对比Streams-Quicknode 指南
高效 RPC 请求指南-Quicknode
Streams 入门指南 - Quicknode 文档
Quicknode Streams