我在繁忙的 postgres 9 数据库前运行 pgBouncer。在大多数情况下,它工作正常。但是每隔几个小时我就会收到一封来自我的应用程序的错误电子邮件,但 psycopg2 有一个例外:
OperationalError('无法连接到服务器:无法分配请求的地址服务器是否在主机“neo-hulk”上运行并接受端口 6432 上的 TCP/IP 连接?')
这是一个 python 应用程序,有一群 celery 工人在运行任务。当这些错误到达时,我检查 pgbouncer db 并且池大小在限制范围内。经过一些实验,我将池最大大小设置为 400,将池大小设置为 200。池模式是“会话”(请求大多是自动提交,几乎没有事务)。
是什么让 pgBouncer 像那样“消失”?它只是在短时间内(总的来说,与处理的请求数量相比,我们谈论的请求数量很少),但那些失败的请求很重要。
谢谢!
错误消息中的“无法分配请求的地址”部分来自内核 TCP 堆栈。当间歇性遇到时,这通常意味着可用套接字的空间已耗尽,因为处于等待状态的套接字过多(
TIME_WAIT
或不太可能FIN_WAIT_1
或FIN_WAIT_2
)可以输出套接字端口的范围
cat /proc/sys/net/ipv4/ip_local_port_range
。普通 Linux 内核的默认值通常是32768 61000
.当系统繁忙时,您可以
netstat -ton|grep WAIT
在客户端和 pgBouncer 的主机上检查结果。该-o
标志将显示与等待状态相关的超时计数器。如果 TCP 套接字的总数接近,
61000-32768=28232
那么这个范围的耗尽可能是您的问题。由于关闭的套接字TIME_WAIT
在正常情况下会花费 60 秒的时间处于状态,如果客户端主机在一分钟内连接超过 28232 次,则新连接将失败并出现上述错误,直到端口被释放。作为第一个解决方法,可以扩展 TCP 端口范围:
如果不满意,请检查
tcp_tw_recycle
andtcp_tw_reuse
标志,也可以通过/proc/sys/net/ipv4
and 进行调整sysctl
。它们被定义为(来自
man tcp
):我个人在遇到 MySQL 客户端应用程序的这个问题时取得了成功
tcp_tw_recycle
,但不要将此作为建议,我对 TCP 的理解充其量只是肤浅的。