【问题标题】:Connection to postgres closed with 'This socket is closed' error message到 postgres 的连接因“此套接字已关闭”错误消息而关闭
【发布时间】:2012-03-31 03:15:48
【问题描述】:

我正在向 node.js 0.6.12 迁移,现在在使用 pg 模块(版本 0.6.14)时收到以下错误消息:

Error: This socket is closed.
at Socket._write (net.js:453:28)
at Socket.write (net.js:446:15)
at [object Object]._send (/home/luc/node_modules/pg/lib/connection.js:102:24)
at [object Object].flush (/home/luc/node_modules/pg/lib/connection.js:192:8)
at [object Object].getRows (/home/luc/node_modules/pg/lib/query.js:112:14)
at [object Object].prepare (/home/luc/node_modules/pg/lib/query.js:150:8)
at [object Object].submit (/home/luc/node_modules/pg/lib/query.js:97:10)
at [object Object]._pulseQueryQueue (/home/luc/node_modules/pg/lib/client.js:166:24)
at [object Object].query (/home/luc/node_modules/pg/lib/client.js:193:8)
at /home/luc/test/routes/user.js:23:29

我的代码中指出的行是:

var get_obj = client.query("SELECT id FROM users WHERE name = $1", [name]);

这个用法可以在节点 0.4.8 和 gp 0.5.0 上正常工作,但现在我正在测试迁移。

我在网上看到几个类似这样的错误,但没有答案。

更新

这似乎与我处理 postgres 连接的方式有关。今天我在运行应用程序时创建了一个连接。我认为在每个请求上创建一个新连接会更好。在快速中间件中创建连接的最佳解决方案是什么?

【问题讨论】:

  • 通常,框架和中间件保持连接打开(或:连接池)。问题很可能在于您的 node.js 代码(或用法)。顺便说一句:如果您可以访问 postgres 的日志文件,您可能会看到与 node.js 的显式断开连接。 (log_connections 和 log_disconnections 都应该设置为 True 才能看到)
  • @wildplasser,在 expressjs 中,我创建了一个中间件,为每个请求打开一个新连接。不确定这是最好的方法,但它解决了这个问题。然后我会检查一下我的连接池。
  • Connect+disconnect 被认为是一项昂贵的操作(TCP 流量、授权、分叉一个工作进程(对于 postgres)、会话设置、日志记录、(会计?))。但如果它对你有用(或者你只有一个请求+回复会话)没关系。
  • @wildplasser,是的,我每个会话只有一个请求。感谢您的建议。你能把你的评论作为答案吗?
  • 所以我做到了。随时为您服务...

标签: postgresql node.js express node-postgres


【解决方案1】:

通常,框架和中间件保持连接打开(或:连接池)。问题很可能在于您的 node.js 代码(或用法)。顺便说一句:如果您可以访问 postgres 的日志文件,您可能会看到与 node.js 的显式断开连接。 (log_connections 和 log_disconnections 都应该设置为 True 才能看到)

Connect+disconnect 被认为是一项昂贵的操作(TCP 流量、授权、分叉一个工作进程(对于 postgres)、会话设置、日志记录、(会计?))。但如果它对你有用(或者你只有一个请求+对会话的回复)没关系。

成本/资源使用估计:

对于会话设置:

  • TCP/IP 连接设置:2*2 IP 数据包:= 4*往返延迟
  • 登录名/密码:
    • 2*2 TCP 读写:= 4 * 往返延迟
    • 4 个系统 R/W 调用
    • 一些用于用户授权的数据库查询/查找,(例如 10...100 次磁盘读取;大部分是缓存的)
    • 会话构建:= fork(用于 postgres)+ 大量 COW 页面被克隆(?100-1000 个页面错误?)
  • 会话初始化:= 几次往返

对于查询:

  • 发送+接收查询:= 几次 TCP/IP 往返
  • 解析 := 几个 (1...100) 目录查找(主要来自磁盘缓存)
  • 执行 := xxx 磁盘读取(可能来自缓存)
  • 获取和存储结果:= 分配(脏)缓冲区
  • 发送结果:= xxx TCP 往返
  • 丢弃结果缓冲区:=(几乎免费!)

会话拆解:

  • 3*2 IP 往返
  • 子进程的exit(),父进程的wait()(对不起,我认为是unix-terms ;-)
  • 1 个套接字描述符处于 TIME_WAIT 状态几秒/分钟

如您所见,建立连接所花费的资源量是典型查询+结果成本的 10 倍,可能是 100 倍;如果您有多个查询要执行,最好保持连接打开。 (或维护一个开放连接池)

为简单起见,我忽略了 CPU 消耗,主要忽略了内存/缓冲区的使用。如今,CPU 几乎似乎是免费的;在等待磁盘 (10 ms) 或网络 (x ms) 时可以完成的计算量令人难以置信:每个字节有几个 (100...10K?) 滴答声。

【讨论】:

  • 详细信息,谢谢。我对每个 http 请求使用一个 db 连接,如果需要多次调用 db 来处理请求,则保持相同的 db 连接。不过,这确实很好。非常感谢。
猜你喜欢
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多