3つのDockerインスタンス(1つはhaproxyを実行し、他の2つはuWsgiを介してFlaskベースのPythonアプリケーションを実行)を持つ設定で、約1日後に1つまたは両方のインスタンスで新しい接続が許可されない状況が発生しました。
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のソースコードは、フィールドを取得するgetsockopt
ためにabdを呼び出してバックログキューの長さを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:プロットが太くなります。ほぼ同じ問題です。この男ただし、MongoDBの代わりにRabbitMQを使用する場合は除外されます。 2番目のスレッドを実行すると、再ロード中に問題が発生し、時にはGILが解放されず、再取得しようとすると中断されることがあります。
基本的に私たちはしてはいけないことをやっていて、すべてをもう一度考えてみる必要があります。