上篇文章我们已经了解了 Supabase Storage ,Storage 用来存储文件。而 Supabase 的 Realtime 则主要用来处理实时通信,对于构建实时性要求很高的应用至关重要,比如即时消息和多人游戏等。实时应用的构建一般比较困难,其难点主要在于连接状态的管理。实时应用一般使用 WebSocket ,需要考虑其连接管理,重连和跨地域连接等。而 Supabase 为你自动处理了这些和运维相关的任务上,可以让你将精力集中在开发产品上。
对于 Realtime,Supabase 提供了 3 种用法,分别用于不同的场景:
- Postgres Changes:数据库变更推送,将后端数据库变更的事件推送到客户端
- Boardcast:基于消息订阅模式的广播消息
- Presence:在线状态同步,可以感知在线状态,在多个客户端共享一个状态时很有用
Postgres Changes
先说这个,Postgres Changes将会把数据库变更事件通过 Websocket 推送给订阅的客户端。客户端在订阅时可以通过参数控制订阅的内容,包括 schema、tables、event(INSERT、DELETE、UPDATE)和filter ,通过这些参数,可以减少发送到客户端的事件数量。
那么在权限控制上是如何控制的呢?确实很简单,这里也是复用了 Database 的 RLS 管理:对于通过客户端订阅的表和行,用户只有在对该表该行存在 SELECT RLS 权限时才能收到该表该行的消息。
Boardcast
接下来聊 Supabase 的 Boardcast。Supabase 的 Boardcast 是一个典型的订阅发布系统,服务端向频道中发布消息,客户端订阅频道获取到推送的消息,所以这里的权限管理就是谁可以订阅什么频道。Boardcast 的 权限管理也是通过 RLS 来进行的,在客户端加入频道时,Boardcast 通过检查 realtime.messages 表上的 SELECT 权限来判断客户端是否有权限加入频道获取消息。因为权限的判断是在加入频道这个时刻,所以当你修改了 RLS 后,已经加入的不受影响,在其离开频道下次加入时才会重新判断评估。那么,我们如何处理 realtime.messages 表上的 SELECT RLS 呢?和之前 Supabase Storage 的 storage.objects 表类似,有哪些几个信息可用于 RLS :
- realtime.messages 表结构,你可以在 Dashboard 中检查表
- auth.uid() 和 current_setting('request.jwt.claims'))::json
- realtime.topic(),该客户端要连接的 topic
Presence
和 Boardcast 不同,Presence 的主要场景是多个用户的在线状态检测和同步。举个例子:在王者荣耀这类的Moba游戏中,一局游戏中的每个人都需要了解所有人的离在线状态和相关位置信息等,并且可以发布自己的状态。Presence就是这样使用的,同一个频道的所有订阅者可以 发布自己的状态,并随时了解到其它订阅者的状态。其权限管理和 Boardcast 完全一样,通过 realtime.messages 表上的 SELECT RLS 控制,就不再赘述了。