RePlaya: 使用 S2 流存储简化会话重放

会话重放工具对于定性用户研究至关重要,它允许开发人员在定量指标提供具有统计学意义的样本之前,准确地看到用户在哪些新功能上遇到了困难。然而,传统的会话重放后端通常是架构上的噩梦,需要复杂的各种消息总线、关系型数据库、对象存储和搜索索引的编排,以处理高容量的 DOM 变更流。

RePlaya 采取了不同的方法。通过构建在 S2 之上,它将每个用户会话视为一个单一的、仅追加的流。这种架构转变极大地减少了基础设施的占用,同时实现了一个在自托管替代方案中经常缺失的强大功能:活动会话的实时尾随(live tailing)。

架构:将流作为事实来源

在典型的会话重放设置中,服务器充当中间人,缓冲事件并将其刷新到数据库或 blob 存储中。RePlaya 消除了这一中间层。使用 S2 Producer API,rrweb 事件被直接追加到会话流的末尾。

这种设计提供了几个技术优势:

1. 统一的存储和检索

与其将元数据拆分为数据库和将实际录制内容拆分为对象存储(如 S3),RePlaya 使用 S2 流作为整个后端。流 就是 录制内容。大型事件被分帧到多个 S2 记录中,并在回放时进行重构,这意味着不需要单独的 blob 存储来管理。

2. 实时实时尾随

由于 S2 流可以在写入时进行尾随,RePlaya 可以通过 Server-Sent Events (SSE) 将新记录桥接到浏览器。这允许开发人员在访问者仍在页面上时实时观看会话,并使用最终将作为历史录制内容的同一流。

3. 简化的列表显示和排序

与其维护一个单独的索引来跟踪会话顺序,RePlaya 使用倒置的时间戳来命名流(例如,sessions/<inverted timestamp>)。由于 S2 按字典顺序对流进行列表显示,一个简单的 prefix list 调用即可首先返回最新的会话,从而消除了使用关系型数据库来跟踪会话年谱的需求。

对比:RePlaya vs. 传统后端

| Feature | Typical Replay Backend | RePlaya | | :--- | :--- | :--- | :--- | | Infrastructure | 消息总线、分析存储、DB、对象存储、搜索索引 | 一个 Node server + S2 | | Live Sessions | 在摄取/刷新延迟后回放 | 通过同一流对活动会话进行实时尾随 | | Stored Recording | 对象存储中的 Blobs;数据库中的元数据 | 每个会话一个有序的 S2 流 | | Footprint | 多服务集群(通常是 Kubernetes) | 单个进程 + S2(或自托管 s2-lite) |

实现与安全

RePlaya 被设计为一个“即插即用”的录制器。只需将一段小的 JavaScript 代码片段添加到目标网站,它就会初始化捕获并将其指向 RePlaya 宿主。

隐私与数据掩码

为了解决会话录制固有的隐私问题,RePlaya 默认实现了掩码功能。它使用 rrwebmaskAllInputs 来确保输入、select 和 textarea 字段中的按键内容(例如密码和电子邮件)永远不会发送到服务器。开发人员可以进一步通过将敏感 DOM 区域包装在 replaya-blockreplaya-ignore 类中,从而将其完全从录制中省略。

生产环境部署

从安全角度来看,RePlaya 将“收集器”(面向公众的写入表面)与“仪表板”(面向私有的读取表面)分离。推荐的生产环境部署涉及:

  • Private Read APIs: 将仪表板和会话检索 API 绑定到私有接口或通过 SSO/VPN 层进行保护。
  • Public Collector: 仅暴露录制器脚本和写入端点,并通过 REPLAYA_ALLOWED_CAPTURE_ORIGINS 和项目密钥进行锁定。
  • Ingest Authentication: 使用在会话创建时生成的短寿命追加令牌来授权后续的事件写入。

伦理考虑

虽然 RePlaya 的技术实现非常精简,但会话重放引发了重要的伦理问题。正如社区讨论中所指出的,许多用户并不知道他们的光标移动和视口变化正在被实时传输到公司的总部。这突出了了定性 UX 数据需求与用户隐私权之间的紧张关系,建议透明的披露或选择性加入机制对于伦理部署可能是必要的。

入门指南

对于希望自托管的用户,RePlaya 可以通过 Docker 或直接通过 Node.js 部署。它支持 S2 Cloud 和自托管的 s2-lite 实例,以便于那些希望将整个基础设施保留在自己的边界内的人。

Sources