开发者进阶中级928 次阅读
事件日志与实时订阅:轮询与 WebSocket 的取舍
轮询简单但延迟不可控,WebSocket 实时却会断线与丢事件。讲清事件日志的检索方式,以及两者如何配合使用。
#事件日志#WebSocket#轮询#监听#可靠投递
一句话结论
轮询实现简单但延迟与请求量都不理想,WebSocket 推送实时但连接会断、事件可能丢。生产环境的答案通常是两者并用。
事件日志是什么
合约 emit 出来的事件被节点记录为日志,并按"合约地址 + 主题(topic)"建立检索维度,这是链上唯一原生的索引结构,应用通常靠它感知"发生了什么"。日志里还带着块号、交易哈希与一个"是否已被移除"的标记——后者与链重组直接相关,却最容易被忽略。
轮询
每次请求"从某个高度到最新高度有哪些日志"。优点是实现简单、无状态、断线即重试,天然适合历史回填与对账;缺点是延迟取决于轮询间隔,间隔越短请求越多,越容易被 RPC 服务限流。
WebSocket 订阅
建立长连接后由节点主动推送新日志。优点是延迟低、请求量小;缺点是连接会因网络抖动、节点重启或长时间空闲而断开,断线期间产生的事件如果处理不当就会永久丢失。此外,不少托管服务的订阅在连接数与订阅数上都有上限。
正确的做法
让订阅负责"快",轮询负责"准":用订阅做实时触发以改善体验,用带检查点的轮询定期补齐可能缺失的高度,并把"已处理到的最后区块"持久化。重连后从检查点回补,而不是从"当前最新块"开始——后者会留下一个永远不补的缺口。
给你的教训
- 任何监听方案都要能回答一个问题:"从上次处理的位置到现在,中间的事件去哪了?"
- 检查点要落库,并且在处理成功之后才更新,否则会永久跳过数据。
- 不要假设事件有序:同块多事件、跨块乱序、重复投递都要能正确处理。
- 只订阅不轮询的实现,几乎一定会在某个时刻漏数据,必须有轮询兜底。