通过组合触发器、PostgreSQL system 和pg_eventserv服务,你可以构建一个实时应用程序,使你的 Web 应用程序完美地保持在与数据库状态同步的状态。LISTEN/NOTIFY
pg_eventserv将 PostgreSQL 事件总线里的事件转换为任何 Web 客户端都可以处理的标准 WebSockets 消息。
对于多用户实时应用程序(例如,车队跟踪器或拍卖系统) ,这种设置可能是一种恩惠!数据库是真相的中心来源,所有应用程序都可以直接在数据库上工作,不需要新的事件总线或系统重新构建。
你的数据库模型
数据库可以被认为是现实世界系统的模型。有时系统是枯燥而抽象的东西,比如会计分类账,有时该系统非常物理,就像送货车队的位置一样,但在大多数情况下,数据库模拟某种系统的状态。
当系统状态发生变化(送货卡车移动,或事务记录到达)时,数据库的状态也应进行相应的更改。有时系统状态会随实际系统的变化而变化,比如当销售点机器更新事务数据库时。有时系统状态会在延迟时发生变化,比如手动输入事务时。但在所有情况下,系统都会跟踪现实世界。
为了理解我们的数据库系统,我们在它们之上构建用户界面。它们可以像 Web 表单一样简单,也可以像程序化的地图一样复杂。
现在,当系统的状态和数据库的状态发生变化时,数据库的用户界面视图会发生什么变化?理想情况下, 接口的状态跟踪数据库的状态:用户看到的是数据库中的内容。
但是,对于长时间处于开放状态而不刷新其源的接口,系统的接口视图很容易与数据库中的实际数据失去同步(这在实时位置数据的映射接口中尤其常见。)
一个简单模型
对于这篇博客文章,让我们用一个跟踪姓名、年龄和身高的表对一组人进行建模。
CREATE TABLE people (
pk serial primary key,
ts timestamptz DEFAULT now(),
name text,
age integer,
height real
);
注意数据变化
注意数据库中的数据变化真的很容易,因为有一个特性专门用于在数据变化时执行操作: TRIGGER。
下面是一个触发器函数,它可以捕获我们的人员模型中的新数据和更新数据。
CREATE OR REPLACE FUNCTION data_change() RETURNS trigger AS
$$
DECLARE
js jsonb;
BEGIN
SELECT to_jsonb(NEW.*) INTO js;
js := jsonb_set(js, '{dml_action}', to_jsonb(TG_OP));
js := jsonb_set(js, '{dml_table}', to_jsonb(TG_TABLE_NAME));
PERFORM (
SELECT pg_notify('people', js::text)
);
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
CREATE OR REPLACE TRIGGER data_change_trigger
BEFORE INSERT OR UPDATE ON people
FOR EACH ROW
EXECUTE FUNCTION data_change();
监听/通知
看看在上面的触发函数中发生了什么! ⬆️⬆️⬆️
对于每次更改数据,该函数将使用行信息准备一个 JSON 对象,然后在该 JSON 对象上使用 pg _ tification ()函数。这是为什么呢?
函数的作用相当于运行 PostgreSQL NOTIFY 命令。NOTIFY 是 LISTEN/NOTIFY命令对的一半。
任何 PostgreSQL 数据库客户端都可以 LISTEN 到指定的通道。NOTIFY 命令将一个文本有效负载放入一个指定的通道,并立即通知所有侦听客户端新的有效负载。这使 LISTEN/NOTIFY 系统成为一个很好的工具,可以确保当客户显示的数据发生某种变化时,客户能够得到通知。
使用 pg _ eventserv 通知 Web 客户端
默认情况下,唯一能够接收 LISTEN/NOTIFY 消息的客户端是使用 PostgreSQL 网络协议直接连接到数据库的客户端。这实际上是一个相当有限的客户选择。大多数现代用户界面都是使用 Web 技术构建的: 有没有办法将 PostgreSQL LISTEN/NOTIFY 消息传递到 Web 客户端?
现在有了,使用 pg _ eventserv!
Pg _ eventserv通过提供 HTML/Javascript 客户端可以连接到的 WebSockets服务,弥补了 PostgreSQL LISTEN/NOTIFY 和 Web 客户端之间的差距。
WebSockets 客户端可以在以下位置连接到pg _ eventserv:
ws://hostname:7700/listen/people
客户端将接收在 PostgreSQL 的“ people”通道上发送的所有消息。在我们的示例中,包括从人员表中捕获的所有更改。
启动pg_eventserv
Pg _ eventserv 程序只是一个用 Go 编写的小型多线程服务。
从 pg _ eventserv 主页下载适合你的操作系统的二进制文件并解压缩它。
将 DATABASE _ URL 环境变量设置为数据库的连接字符串。
运行 pg _ eventserv 程序。
你应该会看到服务启动和连接。如果希望查看更多信息,请使用—— debug 命令行标志运行。
INFO[0000] pg_eventserv latest
INFO[0000] Run with --help parameter for commandline options
INFO[0000] Serving HTTP at http://0.0.0.0:7700/
INFO[0000] Channels available: *
INFO[0000] Connected as 'pramsey' to '' @ '/private/tmp'
创建数据库事件
现在你可以创建数据库事件,并看到它们传播到了你的 Web 浏览器!
连接到 pg _ eventserv 演示用户界面:
http://localhost:7700
在频道栏中输入“ people”,然后单击“ Connect”。
现在转到你的数据库客户端,并向数据库发送一些 SQL 来修改 people 表。
添加一些新的记录:
INSERT INTO people (name, age, height) VALUES ('Paul', 51, 1.9);
INSERT INTO people (name, age, height) VALUES ('Colin', 65, 1.5);
检查网页,你应该在那里看到结果!
为了获得额外的乐趣,请在演示页面上打开几个 Web 选项卡,并指向它们都在的同个频道。请注意它们如何同时接收更新。
数据库作为中心模型
由于数据库已经作为应用程序数据模型的中心真实点,因此保持真实点并在模型状态更改时通知客户机是非常有意义的。
以这种方式构建实时系统允许任何数据库客户端改变系统的状态,并实时将这种改变传播到所有其他客户端。
结论
-
数据库是我们为各种系统存储“记录信息”的地方。
-
用户界面很容易与数据库中的数据状态失去同步。
-
PostgreSQL提供了LISTEN/NOTIFY 系统来实时更新客户端变化。
-
pg_eventserv服务允许你将LISTEN/NOTICE事件进一步推送到任何 WebSockets 客户端。
原文标题:Real-time Database Events with pg_eventserv 原文作者:Paul Ramsey 原文链接:https://www.crunchydata.com/blog/real-time-database-events-with-pg_eventserv




