如何实现PostgreSQL表的实时性?Flutter+Laravel聊天应用开发
让PostgreSQL实现实时性的方案(适配Flutter+Laravel聊天应用)
针对你的场景,这里有几个不用依赖Firebase的靠谱方案,能让PostgreSQL表的变更实时推送给Flutter和Web端:
一、用PostgreSQL原生LISTEN/NOTIFY搞轻量实时
这是最省事儿的方案,直接用PostgreSQL内置的异步消息功能,不需要额外加第三方服务。
1. 数据库加触发器触发通知
给你的聊天消息表(比如messages)加个触发器,当有新消息插入(或更新/删除)时,自动往指定频道发通知:
-- 先写个触发函数,把新消息转成JSON发出去 CREATE OR REPLACE FUNCTION notify_message_change() RETURNS TRIGGER AS $$ BEGIN PERFORM pg_notify('message_updates', row_to_json(NEW)::TEXT); RETURN NEW; END; $$ LANGUAGE plpgsql; -- 给messages表加INSERT触发器,插入后触发上面的函数 CREATE TRIGGER trigger_message_insert AFTER INSERT ON messages FOR EACH ROW EXECUTE FUNCTION notify_message_change();
2. Laravel端监听并转发
Laravel可以开个后台命令,持续监听PostgreSQL的message_updates频道,拿到通知后通过WebSocket推给客户端。比如用beyondcode/laravel-websockets包搭自己的WebSocket服务:
// 写个Artisan命令来监听 Artisan::command('listen:messages', function () { $pdo = DB::connection()->getPdo(); $pdo->exec('LISTEN message_updates'); while (true) { if ($notification = $pdo->pgsql_getnotify(PGSQL_CONNECTION_NOTIFY)) { // 把消息广播给所有订阅的客户端 broadcast(new MessageUpdatedEvent(json_decode($notification['message']))); } usleep(100000); // 避免CPU跑满 } })->describe('监听PostgreSQL消息变更');
3. Flutter端订阅WebSocket
用web_socket_channel包连接Laravel的WebSocket服务,实时接收消息:
import 'package:web_socket_channel/web_socket_channel.dart'; import 'dart:convert'; final channel = WebSocketChannel.connect( Uri.parse('wss://your-laravel-domain/ws'), // 用WSS加密传输 ); // 监听消息流 channel.stream.listen((rawMessage) { final newMessage = jsonDecode(rawMessage); // 更新本地聊天列表UI _chatMessages.add(newMessage); });
二、Laravel Echo + 自研WebSocket服务(功能更全)
如果需要私有频道、在线状态这类进阶功能,用Laravel Echo配合自己搭的WebSocket服务更合适:
- 安装
beyondcode/laravel-websockets和laravel/echo,按文档配置WebSocket服务器。 - 给Message模型加观察者,创建消息时自动广播事件:
// app/Observers/MessageObserver.php public function created(Message $message) { // 广播给其他客户端,自己发的消息本地直接处理就行 broadcast(new MessageCreatedEvent($message))->toOthers(); }
- Flutter端用
laravel_echo包订阅事件:
import 'package:laravel_echo/laravel_echo.dart'; import 'package:socket_io_client/socket_io_client.dart' as IO; Echo echo = Echo({ 'broadcaster': 'socket.io', 'client': IO.io, 'host': 'wss://your-laravel-domain:6001', }); // 订阅公共频道的消息创建事件 echo.channel('messages') .listen('.MessageCreated', (event) { // 处理新消息 _handleNewMessage(event['message']); });
三、逻辑复制(高并发场景用)
如果你的应用用户量很大,并发高,用PostgreSQL的逻辑复制更稳定:
- 先把PostgreSQL的
wal_level改成logical(在postgresql.conf里配置)。 - 创建复制槽,捕获
messages表的所有变更。 - 写个独立服务(比如用Go或Node.js)监听复制槽,解析变更后通过WebSocket推给客户端。
- Laravel和这个服务对接,统一管理实时推送逻辑。
几个注意点
- 用WSS协议加密WebSocket传输,避免聊天数据泄露。
- Flutter端要处理WebSocket重连逻辑,比如断网后自动重新连接。
- LISTEN/NOTIFY不用改
wal_level,但逻辑复制必须开logical。
内容的提问来源于stack exchange,提问作者Debojyoti Sarkar
相关产品推荐
相关产品推荐

