登录

我们为何将 Cliqer 的实时服务迁离 Cloudflare(以及为何我们依然是它的粉丝)

在 Cloudflare 边缘运行的四个月:哪些地方出了问题,我们为应对构建了什么,以及 Cliqer 为何如今运行在我们自己的专用服务器上。

Cliqer Team

2026年9月25日 · 阅读时长 2 分钟

A dedicated server rack glowing mint in a dark data hall

2026 年 9 月 24 日 18:42(UTC),我们将所有 Cliqer 实时连接从 Cloudflare Workers 和 Durable Objects 迁移到了我们自己的专用服务器上。我们尝试过边缘计算,而这一次,它让我们失望了。如果您正在使用 Cliqer,您的工作方式不会有任何变化。变化发生在底层:您的房间不会再因为无人能解释的原因而重启。

本文将坦诚地讲述其中的原因。这也是一封感谢信,因为我们仍然是 Cloudflare 的客户,也依然真心欣赏他们打造的产品。

要点速览
  • 在四个月里,每个 Cliqer 房间都运行在 Cloudflare Durable Objects 上。这个构想很美妙:每个房间都在边缘拥有一台属于自己的、始终在线的小型服务器。
  • 实际上,Cliqer 的房间每天都会在底层被重启数次,既没有触及内存上限,也没有触及 CPU 上限,我们的代码没有报错,也没有任何部署。每次重启都会断开该房间内的所有连接。
  • 我们构建了大约 18 种不同的机制,来向您隐藏这些重启。有些奏效了。但这种复杂性本身开始引发新的 bug。
  • Cliqer 的实时服务现在运行在我们自己的专用服务器上,仍然位于 Cloudflare 的网络之后。没有意外重启,没有存储重置,也没有「位置抽签」。
  • 速度也更快了:桌面应用的启动检查响应速度最高提升 17 倍,空闲连接的建立时间从 1.2 秒缩短到 0.14 秒。
  • 如果现在连接断开,原因是明确的:您的网络、一次约一秒即可完成重连的计划更新,或者不可抗力。它不再是一个谜。

我们想要构建什么

Cliqer 是一款现场工具。演讲者轻点手机,一块可能远在另一个大洲的屏幕上的幻灯片随即翻页。连线嘉宾加入节目,主持人切换信号源,计时器在舞台上倒数。这一切都依赖 WebSocket:这种长连接绝不能有丝毫闪断,因为一旦闪断,就会发生在观众面前。

Durable Objects 看起来是完美之选。每个房间都拥有一个单线程对象,持有自己的套接字和存储,运行在 Cloudflare 的网络上。无需管理服务器,无需规划扩容。到 5 月下旬,所有房间都已运行在其上,旧版 Cliqer v1 桥接服务也在 6 月加入。

出了什么问题

无法解释的重启

Durable Object 随时可能被平台重启,而一旦重启,它持有的每个 WebSocket 都会被关闭。我们专门针对这一点检查了一个 24 小时窗口内的日志:没有一个套接字在重启后存活。 一个都没有。

如果重启很少发生,这也无妨。但事实并非如此:

  • 位于里斯本、承载所有房间的那个对象在 5 天内重启了 21 次,其中 4 次发生在同一个小时内。没有内存溢出,没有触及 CPU 上限,只有少量平台内部错误,而我们也没有进行任何部署。
  • 我们迁移了它。Durable Objects 会停留在首次创建的位置,因此迁移意味着重新创建它,并祈祷它落在更好的地方。第一次尝试落在了马德里,下一次落在了阿姆斯特丹。
  • 在阿姆斯特丹,重启依然接连不断,每隔 2 到 16 小时一次,平均约每 8.7 小时一次。
  • 到了 9 月,服务旧版房间的那个对象仍在无故每天重启 2 到 5 次。9 月 8 日 18:53,所有旧版连接在同一毫秒内全部关闭。我们没有部署,状态页面上也没有任何事故通报。

对您而言,每一次重启都意味着演示遥控器停止响应、连线嘉宾突然消失,或者应用在节目进行中提示正在重新连接。

超时并重置房间的存储

9 月 7 日至 10 日期间,我们在 4 个对象上共 8 次看到这条错误信息:“Durable Object storage operation exceeded timeout which caused object to be reset”。其中一次重连尝试等待了 44.5 秒才宣告失败。本应只需几毫秒的存储读取,却让整个房间随之瘫痪。

每次部署都会重启所有房间

这一点有文档说明,也合情合理:发布新版本的 Worker 会重启其 Durable Objects,而重启它们就会关闭其上的连接。8 月 19 日至 21 日期间,在线客户房间中 44% 的重连是成批同步发生的,而我们自己在一天内的三次发布导致所有房间断开,其中一次正值节目进行中。

于是我们将套接字拆分到独立的 Worker 中,并构建了一个工具,检查每个改动的文件,判断哪些部署允许触及房间。这个办法奏效了:下一次网站发布时,有五位主持人在线,房间事件为零。但这也意味着,任何对实时代码的改动仍会重启所有人的连接。

在现场节目中坑了我们的微妙行为

  • 长达 16 分钟的静默。 8 月 4 日,43 个套接字保持连接,但没有任何消息被投递到任何房间。边缘一直在代替房间响应心跳,因此没有客户端察觉到异常,也没有人重新连接。这源于我们刚刚启用的一项平台功能,再加上我们自己的状态记录逻辑。我们在同一周内就回退了这项改动。
  • 幽灵主持人。 关闭事件并不保证能送达处于休眠状态的对象,因此一位早已离开的主持人可能在数小时内看起来仍然在线。
  • 一个被缓存卡住四小时的 URL。 8 月,我们 Worker 前面的一层缓存卡在了桌面应用启动时检查的那个 URL 上。应用无法启动。而同一个 URL 加上一个无意义的参数,一秒内就能得到响应。

我们为应对而构建的东西

在这四个月里,我们构建了大约 18 种独立机制来向您屏蔽平台问题:更快的心跳、清理幽灵主持人的扫描、每次唤醒时从存储中重建的注册表、在重启后依然保留的身份标识(以便您的应用能够恢复会话)、独立的套接字 Worker、覆盖 161 个文件的部署分类器、重新抽取部署位置、中继看门狗、按房间分片,以及与之配套的跨分片席位账本。

其中三项后来被我们删除了,因为它们带来的麻烦比解决的问题还多。而且每一个变通方案都增加了更多活动部件。将房间分片到多个对象之后,我们遇到了一个替错误分片作答的失控房间、一个陷入迁移循环的观众,以及一个可以跨分片绕过的席位上限。每个问题都得到了修复,但我们把时间花在了绕开平台的工程上,而不是打造 Cliqer。

公平地说

那几个月里,并非每一次连接断开都是 Cloudflare 的问题。我们核查过:

  • 86% 的单次重连是单台设备因自身网络而断开:企业代理、场馆 Wi-Fi、排斥长连接的防火墙。这也是我们在 8 月为桌面应用推出企业网络支持的原因。
  • 有些成批断连是我们自己的部署造成的,还有几次是我们自己的调试工具引起的。
  • 我们从未就这些重启提交过支持工单。这是我们的责任。

Durable Objects 是一项出色的工程成果,对许多工作负载来说,它恰恰是正确的选择。而一个面对现场观众、绝不能闪断的房间,对于一个可以随时重启它的平台而言,恰好是最坏的情况。我们尝试将边缘用于实时服务,而这一次,它让我们失望了。这是对这类工作负载的结论,而非对边缘计算本身的评判。

现在由什么承载您的房间

Cliqer 的实时服务现在运行在我们自己的专用服务器上。它们负责网站、API 和所有 WebSocket,直接承载每个房间,并以本地数据库作为支撑。流量仍然经过 Cloudflare 的网络,因此您依然享有同样的防护和同样的地址。

消失的问题:

  • 不再有来自底层的重启。进程会一直运行,直到我们决定停止。
  • 不再有位置抽签,也不再有存储超时导致房间重置。
  • 不再分片。一个房间,一个位置,一个唯一可信的数据源。

我们坦诚说明的事项:

  • 当我们发布更新时,您的连接会重连一次。 新版本会在旧版本旁边启动,并几乎瞬间接管。您的应用会在约一秒内以相同的身份重新连接,并从原来的状态继续运行。在我们的演练中,4,757 个网页请求经历了切换,无一失败。
  • 我们的服务器位于欧洲。我们宁愿运行自己完全理解的机器,也不愿依赖数百个无法洞察其内部的地点。

速度也更快了

我们会在自己这边记录每个 API 请求的耗时,因此可以用真实流量而非实验室测试,对比迁移前一周与迁移后几天的数据。

17x

桌面界面检查提速

10x

版本检查提速

0.14 s

即可建立空闲连接,此前为 1.2 s

4x

团队仪表板统计提速

应用正在执行的操作之前(中位数)之后(中位数)提速倍数
桌面应用检查界面更新178 ms10 ms17x
桌面应用检查新版本344 ms32 ms10x
获取视频中继凭据210 ms56 ms3.8x
加载您团队的仪表板统计数据973 ms240 ms4x
检查您的许可证和套餐268 ms119 ms2.3x

最慢的请求改善得更加明显。仪表板品牌加载中最慢的十分之一从 1.7 秒降至不到半秒,而最慢的中继凭据获取则快了 7 倍。

最大的变化是您最先感受到的。在旧平台上,一个闲置过的实时连接在唤醒过程中需要约 1.2 秒才能建立。在我们自己的服务器上,它每次都只需约 0.14 秒。我们的独立可用性监控每分钟从北美检查一次 cliqer.io,结果也印证了这一点:迁移前每次检查约 750 ms,迁移后约 380 ms。

在房间内,点击本来就很快,现在依然如此。变化的是点击之外的一切:打开应用、加载演讲者页面、获取您的账户信息。这一切都响应得更快,而且每次都同样稳定。

Cloudflare 仍在为我们做什么

很多,而且我们乐于如此:

DNS

用于每一个 Cliqer 域名。

代理、CDN 和防火墙

位于 cliqer.io 前端(包括 WebSocket),并且只允许 Cloudflare 的边缘访问我们的服务器。

TURN 中继

帮助您的视频穿越受限网络。

团队自定义域名

包括证书,以及桌面应用更新的存储。

他们的可观测性和分析工具也让本文中的大部分诊断成为可能。我们仍然是他们的客户,也依然推荐他们。

演示遥控器延迟:为什么毫秒至关重要

从您轻点屏幕到幻灯片翻页之间,究竟发生了什么。

我们如何让屏幕共享提速四倍

今年夏天的另一个重大性能故事。

穿越企业防火墙

为什么大多数单设备断连源于网络,以及 Cliqer 如何顺利穿越。

安全与网络文档

端口、中继,以及您的 IT 团队需要放行的内容。

如果连接断开,请告诉我们

我们的承诺很简单:现在当连接断开时,我们一定能找到原因。如果您发现 Cliqer 在节目中途重新连接(这里有幻灯片卡住时该怎么办的现场应对方法),请回复我们的任意一封邮件,或在应用中发起聊天。我们会阅读每一条消息,而现在,我们真的能告诉您原因了。

reliabilitywebsocketscloudflarededicated serversengineering

由Cliqer Team撰写

我们打造了 Cliqer,这款互联网遥控器正在全球各地的舞台、教室和会议室中使用。

用 Cliqer 掌控您的下一场活动

任意幻灯片,任意手机,随时随地。桌面应用托管房间,演讲者只需打开链接。

继续阅读

更多产品动态,助力您的下一场活动

A presenter holds a phone remote: one half seen through a thermal camera glowing hot, the other half cool in mint stage light
产品动态

我们为何抛弃 Flutter 应用,基于 Rust 核心原生重建 Cliqer Remote

我们用 Flutter 构建了 Cliqer Remote,在真实手机上实测后,又基于同一个 Rust 核心原生重建:耗电减半,不再发热。这里是数据与经验。
A software engineer reviewing a video latency graph on a monitor in a dimly lit office
产品动态

我们如何将屏幕共享提速四倍

将 Cliqer 屏幕共享延迟从两秒多降至约半秒,背后的工程故事。
A bright hybrid meeting room with a camera on a tripod and a laptop running Cliqer Studio
现场制作

Cliqer vs Ecamm Live:哪款直播工作室更适合您的节目?

公平对比 Cliqer 与 Ecamm Live:支持 Mac 和 Windows 的 Studio、Live、Timer 与手机遥控,对比仅限 Mac 的直播工作室。
简报

赶在您的下一场活动之前,抢先获取下一篇指南

为演讲者、AV 团队和活动团队提供实用指南,以及真正重要的 Cliqer 版本更新。绝无垃圾邮件,一键即可退订。