pgBouncer效果很好,但偶尔变得不可用


9

我正在繁忙的postgres 9数据库前面运行pgBouncer。在大多数情况下,它都可以正常工作。但是每隔几个小时,我就会收到来自应用程序的错误电子邮件,以及来自psycopg2的异常消息:

OperationalError('无法连接到服务器:无法分配请求的地址服务器是否在主机“ neo-hulk”上运行并接受端口6432上的TCP / IP连接?”)

这是一个Python应用程序,其中有许多芹菜工作者正在运行任务。当这些错误到达时,我检查pgbouncer db,并且池大小在限制范围内。经过一些试验后,我将池的最大大小设置为400,池的大小设置为200。池模式是“会话”(请求大部分是自动提交的,几乎没有事务)。

是什么使pgBouncer像这样“消失”?它仅在短时间内(总的来说,与处理的大量请求相比,我们谈论的是很少的请求),但是那些失败的请求很重要。

谢谢!


操作系统和版本?内核版本是否为Linux?确切的PostgreSQL和Pg​​Bouncer版本?您是否在调试日志级别运行PgBouncer并查看它是否报告了有用的信息?
Craig Ringer

Debian 6. Linux版本2.6.32-5-amd64(Debian 2.6.32-48squeeze1)pgbouncer版本1.5.4 Postgres 9.1。日志不记录连接/断开连接,因为我认为这有点多,但是当引发这些应用程序错误时,没有错误存在。错误来自psycopg2,认为没有db服务器可以与之交谈,尽管在pgbouncer之前不存在此问题
Harel

1
嗯,所以是当前的PgBouncer,内核是古老的但很稳定。我认为您需要在PgBouncer中启用更详细的日志记录,-vvv并查看是否可以及时将异常日志输出与错误进行匹配。
Craig Ringer 2014年

我做了一个“ set verbose = 1; reload;” 在pgbouncer shell中,并且在日志中找不到任何异常。这是一个生产系统,因此无法停止该服务以-vvv作为非守护程序运行。希望我有同样的结果。请注意,该错误表明它根本无法连接到pgbouncer,即找不到在该端口监听的信息。一直有成千上万的连接,奇怪的是很少有连接会像这样失败。
哈雷尔2014年

整rick; 听起来像是潜在的比赛状况,但是在什么地方/什么地方...
Craig Ringer 2014年

Answers:


15

错误消息中的“ 无法分配请求的地址 ”部分来自内核TCP堆栈。间歇性遇到时,这通常意味着可用套接字的空间已用完,因为处于等待状态的套接字过多(TIME_WAIT,或者可能性较小,FIN_WAIT_1FIN_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端口范围:

 # echo "1025 65535" >/proc/sys/net/ipv4/ip_local_port_range

如果不满意,请检查tcp_tw_recycletcp_tw_reuse标志,也可以通过/proc/sys/net/ipv4和进行调整sysctl

它们被定义为(from man tcp):

       tcp_tw_recycle(布尔值;默认值:禁用;从Linux 2.4开始)
              启用TIME_WAIT套接字的快速回收。启用这个
              不建议使用此选项,因为这会在工作时引起问题-
              NAT(网络地址转换)。

       tcp_tw_reuse(布尔值;默认:禁用;自Linux 2.4.19 / 2.6起)
              允许重新使用TIME_WAIT套接字进行新连接
              从协议的角度来看是安全的。没有它就不能改变
              咨询/请求技术专家。

就个人而言tcp_tw_recycle,面对MySQL客户端应用程序的此问题,我取得了成功,但我不建议这样做,因为我对TCP的理解充其量只是肤浅的。


1
该答案表明任何对TCP的错误肤浅理解。谢谢你 我增加了端口范围,让它运行一段时间以查看它是否有作用。(设置后是否需要重启?)
Harel 2014年

我认为港口增加已经做到了。到目前为止,我还没有收到任何错误。netstat行的粗略计数显示客户端中的接近20K,因此从那里到28K的默认限制不长。感谢那!
Harel 2014年

1
好!你想要把设置在/etc/sysctl.confnet.ipv4.ip_local_port_range = 1025 65535拥有它持续到重新引导。
DanielVérité2014年

谢谢。从那以后我收到了错误,但没有收到,因此还是不错的。让它运行几天,将使烫发发生变化。我很高兴到目前为止,这种方法似乎奏效了,因为其他变化吓到了我:)
Harel 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.