Realtime: Handling Silent Disconnections in Background Applications
如果你的 Supabase 实时订阅在一段时间后停止接收事件,但没有任何明确的错误信息,那么你可能遇到了静默断开连接的问题。本指南解释了发生这种情况的原因,并提供了保持连接稳定的可靠解决方案。
🌐 If your Supabase Realtime subscriptions stop receiving events after some time without any explicit error messages, you might be experiencing a silent disconnection. This guide explains why this occurs and provides robust solutions to maintain connection stability.
关键技术概念 #
🌐 Key technical concepts
要理解这个问题及其解决方案,首先明确一些核心技术术语会很有帮助:
🌐 To understand the problem and its solutions, it's helpful to first define some core technical terms:
- 什么是 Supabase Realtime? Supabase Realtime 是一项服务,它允许你的应用在数据发生变化时,实时监听并接收来自 Postgres 数据库的即时更新(事件)。它使用 WebSocket 连接来提供这种实时数据流。
- 什么是 WebSocket? WebSocket 是一种通信协议,它可以在单个 TCP 连接上提供全双工、持久的通信通道。与传统的 HTTP 请求不同,WebSocket 允许客户端(比如你的应用)和服务器之间进行持续的双向通信,非常适合实时应用。
- 什么是心跳? 在网络连接的上下文中,心跳是两个已连接实体之间定期发送的信号(例如,你的客户端和实时服务器),用来确认连接仍然活跃并且双方都能响应。如果在一段时间内没有收到心跳信号,可能表示连接已经中断。
- 什么是浏览器限流? 浏览器限流是一种由网页浏览器使用的优化策略,用来在标签页或应用在后台运行或不活跃时节约资源(CPU、电量)。这通常涉及降低 JavaScript 定时器的频率,从而可能减慢或暂停后台操作。
- 什么是 Web Worker? Web Worker 是一种在后台运行的 JavaScript 脚本,它独立于主浏览器线程。这意味着可以执行复杂的计算或长时间运行的任务,而不会冻结或影响用户界面的响应能力。
理解问题:为什么 Realtime 会悄无声息地停止 #
🌐 Understanding the problem: Why Realtime stops silently
Supabase Realtime 依赖保持持久的 WebSocket 连接来传递实时更新。为了确保这个连接处于活跃和健康状态,Realtime 客户端会定期向服务器发送“心跳”信号。
🌐 Supabase Realtime relies on maintaining a persistent WebSocket connection to deliver real-time updates. To ensure this connection is active and healthy, the Realtime client periodically sends "heartbeat" signals to the server.
核心问题出现在你的应用,尤其是网页应用,当它进入后台状态时(比如浏览器标签页不再活跃,或者应用被最小化)。在这种情况下,网页浏览器通常会实现浏览器节流。这意味着浏览器会在后台降低 JavaScript 定时器的执行频率。
🌐 The core issue arises when your application, particularly if it's a web application, moves into a background state (e.g., the browser tab is no longer active, or the application is minimized). In such scenarios, web browsers often implement browser throttling. This means the browser reduces the execution frequency of JavaScript timers in the background.
当 JavaScript 定时器被限制时,实时客户端可能无法按照要求的间隔发送心跳。如果服务器长时间没有收到心跳,它会认为客户端已断开连接,WebSocket 连接可能会悄无声息地断开。这样你的应用就会停止接收事件,而且不会有任何明确的错误信息,因为客户端主线程并没有主动检测到连接丢失。网络不稳定也可能导致这种无声断开。
🌐 When JavaScript timers are throttled, the Realtime client might be prevented from sending its heartbeats at the required intervals. If the server doesn't receive heartbeats for too long, it assumes the client has disconnected, and the WebSocket connection can silently drop. Your application then stops receiving events without any explicit error message, as the connection loss was not actively detected by the client's main thread. Network instability can also contribute to silent disconnections.
强大的实时连接管理解决方案 #
🌐 Solutions for robust Realtime connection management
为了确保你的实时订阅在后台状态下仍能保持稳定,并能抵御无声断开,Supabase 提供了两种推荐策略,可以结合使用。
🌐 To ensure your Realtime subscriptions remain stable and resilient against silent disconnections, especially in background states, Supabase provides two recommended strategies that can be used together.
步骤 1:实现 heartbeatCallback#
🌐 Step 1: Implement heartbeatCallback for explicit reconnection
heartbeatCallback 选项让你可以主动监控实时连接的状态,并且如果检测到断开连接,可以通过程序触发重新连接。
🌐 The heartbeatCallback option allows you to actively monitor the status of your Realtime connection and programmatically trigger a reconnection if a disconnection is detected.
- 目的: 了解连接的健康状况,并为你的应用提供在连接丢失时显式重新连接的机制。
- 工作原理: 当你初始化
RealtimeClient时,你可以提供一个heartbeatCallback函数。每当实时客户端的内部心跳机制检测到连接状态变化时,这个函数就会被调用。通过检查传给回调的status是否为'disconnected',你就可以调用client.connect()尝试重新建立 WebSocket 连接。
1const client = createClient(SUPABASE_URL, SUPABASE_KEY, {2 realtime: {3 heartbeatCallback: (status) => {4 if (status === 'disconnected') {5 // Explicitly reconnect when heartbeat fails or connection drops6 client.connect()7 }8 },9 },10})步骤 2:启用 Web 工作者以实现可靠的后台心跳 #
🌐 Step 2: Enable Web workers for reliable background heartbeats
启用 Web Worker 选项有助于防止浏览器限速影响你的实时连接的心跳机制。
🌐 Enabling the Web Worker option helps prevent browser throttling from affecting your Realtime connection's heartbeat mechanism.
- 目的: 确保即使你的应用在后台运行时,也能持续发送心跳信号,从而防止浏览器限速导致的无声断开连接。
- 工作原理: 在你的 Realtime 客户端配置中设置
worker: true后,心跳逻辑会被卸载到 Web Worker。由于 Web Worker 在独立线程中运行,相比在非活跃标签页的主线程上执行的 JavaScript,它通常不容易受到浏览器限流影响。这就能让心跳在后台可靠发送,从而保持 WebSocket 连接的活跃。
1const client = createClient(SUPABASE_URL, SUPABASE_KEY, {2 realtime: {3 worker: true,4 },5})建议:把两种方案结合起来,效果更稳 #
🌐 Recommendation: Combine both solutions for maximum stability
为了实现最稳定的实时连接管理,强烈建议同时使用 heartbeatCallback 和 worker: true 选项。
🌐 For the most robust Realtime connection management, it is strongly recommended to combine both the heartbeatCallback and the worker: true options.
worker: true选项作为一种主要的预防措施,主要减少了由于浏览器在后台标签限制而导致断线的风险。它能确保心跳信号可靠发送。heartbeatCallback充当了一个关键的备用和监控机制。它让你的应用能够检测并应对可能由于其他原因(比如网络不稳定)而发生的任何断开连接,从而确保客户端始终可以尝试重新建立连接。