3개의 도커 인스턴스(하나는 haproxy를 실행하고 다른 2개는 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의 소스 코드는 필드를 검색하기 getsockopt
위해 abd를 호출하여 백로그 큐 길이를 tcpi_unacked
얻는다는 것을 보여줍니다. 즉, 이것은 uwsgi의 버그가 아닌 것 같습니다. Linux 커널 및/또는 docker는 실제로 존재하지 않는 연결이 있다고 생각하는 것 같습니다. 나는 haproxy가 수행하는 건강 검진의 형태로 그런 일이 존재했다고 의심합니다.
백로그 로그가 느리게 증가하지 않습니다. 인스턴스가 잘 실행되는 동안 백로그는 여전히 0입니다. 뭔가 잘못된 것 같았고, 주문 잔고가 곧 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를 사용하는 경우는 제외됩니다. 두 번째 스레드를 실행하면 다시 로드하는 동안 문제가 발생하고 때로는 GIL이 해제되지 못하고 다시 획득하려고 할 때 중단되는 경우가 있습니다.
기본적으로 우리는 해서는 안 될 일을 하고 있고 모든 것을 다시 생각해 볼 필요가 있습니다.