uwsgi 的 TCP 积压量很大,但没有可见的连接

uwsgi 的 TCP 积压量很大,但没有可见的连接

在具有三个 docker 实例的设置中,一个运行 haproxy,另外两个通过 uWsgi 运行基于 Flask 的 python 应用程序,我们在大约一天后遇到一种情况,一个或两个实例上不接受新连接。

uWsgi 设置为接受最多 100 个积压连接。这小于 中配置的默认 128 /proc/sys/net/core/somaxconn。 uWsgi 放弃第 101 个连接。

ss确认积压数量为 101。

root@ad9380a94c50:/# ss -nlpt
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN     101    100                       *:8080                     *:*      users:(("uwsgi",pid=25,fd=3),("uwsgi",pid=19,fd=3))
LISTEN     0      128              127.0.0.11:38230                    *:*

运行时没有对应的连接,例如netstat -npt

uwsgi的源码显示,backlog队列长度是通过调用getsockoptabd检索tcpi_unacked字段得到的。换句话说,这似乎不是 uwsgi 中的错误,Linux 内核和/或 docker 似乎认为存在实际上并不存在的连接。我怀疑它们曾经存在过,以 haproxy 进行的健康检查的形式存在。

不会出现积压日志缓慢增加的情况。虽然实例运行良好,但积压仍为零。好像出了什么问题,之后积压的订单很快就达到了 100,事情就挂了。

我们在 Amazon 虚拟机上运行 docker。

答案1

该进程在互斥体(或 Linux 中的 futex)上阻塞。所以积压是合法的,我们实际上被困在系统调用后面,尽管连接消失了,但没有其他更新。

为了将来给发现这个问题的其他人提供参考,这是突破性的命令:

# strace -p 5340
Process 5340 attached
futex(0x223cee0, FUTEX_WAIT_PRIVATE, 0, NULL

所以存在某种死锁,我现在只需弄清楚哪个进程正在使用互斥体。gdb最终给了我这些信息:

(gdb) bt
#0  sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:85
#1  0x00007f0ecc982068 in PyThread_acquire_lock () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
#2  0x00007f0ecd037b29 in gil_real_get () from /usr/lib/uwsgi/plugins/python_plugin.so
#3  0x00007f0ecd030167 in uwsgi_python_master_fixup () from /usr/lib/uwsgi/plugins/python_plugin.so
#4  0x000000000042cb66 in uwsgi_respawn_worker ()
#5  0x000000000042b38f in master_loop ()
#6  0x000000000046741e in uwsgi_run ()
#7  0x000000000041698e in main ()

因此,在尝试获取全局解释器锁时会出现某种死锁。

编辑2: 情节变厚了。几乎完全相同的问题这家伙,只不过我们使用的是 RabbitMQ 而不是 MongoDB。运行第二个线程会导致重新加载期间出现问题,有时会导致 GIL 无法释放,然后在尝试重新获取它时挂起。

基本上,我们正在做一些不应该做的事情,只需要重新思考整个事情。

相关内容