我使用的是Postgres 9.5,它有一个名为LISTEN/NOTIFY
的功能,允许您设置一个异步命令通道来从服务器获取通知。在我的应用程序运行和测试通知的前10-15分钟,一切似乎都正常,但过了一定时间后,消息似乎就被丢弃了。
有人对如何防止这种行为有什么建议吗?这与keep-alive/tcp keep-alive设置有关吗?在pg_state_activity中,我看到了相同的连接,它处于空闲状态。
情况概述
- 使用c#中的npgsql库到非现场Postgresql服务器
- 使用长时间运行的连接(安装程序侦听,等待(
- 执行查询以侦听传入通知和通知
- 等待(带有取消令牌(,直到收到消息(连接上没有发生其他活动(
查看StackOverflow上的其他一些答案,人们似乎也将其归因于池化,尽管我不完全确定这是否能很好地转化为npgsql
,因为它在连接/断开连接时池化连接。
我很感激人们对这个问题有任何见解,有人知道我如何让我的处境发挥作用吗?以下是罪魁祸首的代码片段:https://gist.github.com/phr34k/3a59af154d8ce6636dfc332271052a6a
编辑
针对贾尼斯的答复,我进行了进一步调查。当我查看pg_state_activity
时,它列出了处于空闲状态的连接。当我在服务器上交叉引用客户端端口号和netstat -t
时,至少我看不到列出的连接。
公平地说,在我运行netstat -t
之前,我确实尝试过pg_notify
,所以我还不能确定运行pg_notify
是否没有导致它终止。然而,奇怪的是,连接一直显示在pg_state_activity
中,就好像postgres甚至没有意识到连接已经关闭一样?
我认为这与防火墙和空闲连接有关。有人知道ubuntu/数字海洋堆栈中是否有任何默认值会在一段时间后杀死连接吗?
如果不调用UNLISTEN或关闭,我认为任何事情都不会使连接停止侦听。最可能的解释是连接被切断,然后连接池通过重新建立连接来掩盖这一点,在这种情况下,新的连接将不会侦听。应该在客户端和服务器端记录此事件。你在日志中看到了在这种情况下有意义的东西吗?
"idle"是pg_stat_activity中的正常"状态",它只做倾听,所以这对你没有帮助。但是"backend_start"列可能会有所帮助,这与关闭和重新打开的连接一致吗?"state_change"一开始可能看起来很有希望,但它似乎不会仅仅在客户端读取通知后更新。我看不出一个会话可以检测是否有其他会话在侦听。pg_listening_channels((仅适用于发出它的连接。
等待(带有取消令牌(,直到收到消息(连接上没有发生其他活动(。
取消标记意义重大吗?你用过吗?是否可以共享实现此等待的代码片段?
我认为10或15分钟的时间不足以让TCP决定连接已经断开,所以如果连接被切断,很可能是一些主动的东西在做这件事,比如防火墙。如果是这样的话,它可能会"看穿"保持活动,并决定无论如何都要断开连接。