我想使用 WebSockets 广播用户通知,并使用 PostgreSQL NOTIFY 语法发送它们。
我还想避免在解决方案中引入另一个服务器——无论是 Redis、RabbitMQ 等
这可行吗? PostgreSQL 中的异步 LISTEN 有问题吗?
是的,这是可行的。 postgresql NOTIFY/LISTEN 特性允许有效地通知客户,因为客户不必定期轮询表以获取更改或类似的东西。相反,用 epoll/poll/select 注册数据库连接的文件描述符(用于读取准备)就足够了,这样进程就可以休眠直到下一个通知,以防它没有更好的事情要做。
像 psycopg 这样的包在底层做这个。最小的 psycopg3 示例:
import psycopg
db = psycopg.connect('dbname=somedb ...', autocommit=True)
db.execute('LISTEN testchannel')
xs = db.notifies()
for x in xs:
print(x)
负载大小和服务器端缓冲有一些技术限制,但在实践中似乎很难超过。有关详细信息,请参阅postgresql 文档:
payload [..] 在默认配置中它必须小于 8000 字节。 (如果需要通信二进制数据或大量信息,最好放在数据库表中,并发送记录的键。)
有一个队列保存已发送但尚未被所有监听会话处理的通知。如果此队列已满,调用 NOTIFY 的事务将在提交时失败。队列非常大(在标准安装中为 8GB)并且应该足以满足几乎所有用例。但是,如果会话执行 LISTEN 然后进入事务很长时间,则无法进行清理。