Я размещаю приложение, состоящее из нескольких модулей Python. Пока мы используем Apache в рабочем режиме MPM и mod_wsgi, который является рабочей средой.
Теперь мы хотим проверить, может ли nginx + uwsgi быть более производительной средой. Python - это Python 2.6.6, а uwsgi - 2.0.7. У меня есть следующая конфигурация uWSGI для моего приложения (сокращенный пример):
[uwsgi]
chdir = /path/to/app
chmod-socket = 777
no-default-app = True
socket = /tmp/socket.sock
master = 1
processes = 4
threads = 2
enable-threads = true
touch-reload=/root/uwsgi.ini
manage-script-name = True
mount = /accounts=account.py
[... several more mount directives ...]
mount = /ping=ping.py
[... several more mount directives ...]
mount = /subscriptions=subscription.py
callable = application
enable-logging = 1
plugin = /usr/lib/uwsgi/stats_pusher_statsd
stats-push = statsd:graphite-int.cern.ch:8125:uwsgi-test
enable-metrics = 1
memory-report = 1
stats = /tmp/stats.sock
Когда я запускаю uWSGI вот так, сначала все выглядит хорошо:
[uWSGI] getting INI configuration from rucio.wsgi.ini
*** Starting uWSGI 2.0.7 (64bit) on [Mon Aug 25 19:15:07 2014] ***
compiled with version: 4.4.7 20120313 (Red Hat 4.4.7-4) on 22 August 2014 22:51:22
os: Linux-2.6.32-431.3.1.el6.x86_64 #1 SMP Mon Jan 6 11:34:51 CET 2014
nodename: rucio-server-dev-ngnix
machine: x86_64
clock source: unix
detected number of CPU cores: 4
current working directory: /root
detected binary path: /usr/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
your processes number limit is 63837
your memory page size is 4096 bytes
detected max file descriptor number: 4096
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 inherited UNIX address /tmp/rucio.sock fd 3
Python version: 2.6.6 (r266:84292, Jan 23 2014, 10:39:35) [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)]
Python main interpreter initialized at 0x26b1c00
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 415360 bytes (405 KB) for 8 cores
*** Operational MODE: preforking+threaded ***
initialized 108 metrics
mounting account.py on /accounts
WSGI app 0 (mountpoint='/accounts') ready in 1 seconds on interpreter 0x26b1c00 pid: 2839
[... several more mount outputs like the one above ...]
mounting ping.py on /ping
WSGI app 8 (mountpoint='/ping') ready in 2 seconds on interpreter 0x9b020b0 pid: 2839
[... several more mount outputs like the one above ...]
mounting trace.py on /traces
WSGI app 15 (mountpoint='/traces') ready in 2 seconds on interpreter 0xf393210 pid: 2839
*** uWSGI is running in multiple interpreter mode ***
gracefully (RE)spawned uWSGI master process (pid: 2839)
spawned uWSGI worker 1 (pid: 2986, cores: 2)
spawned uWSGI worker 2 (pid: 2988, cores: 2)
spawned uWSGI worker 3 (pid: 2990, cores: 2)
spawned uWSGI worker 4 (pid: 2992, cores: 2)
metrics collector thread started
*** Stats server enabled on /tmp/rucio-stats.sock fd: 16 ***
Но как только поступает первый запрос, независимо от запрошенной точки монтирования, я получаю следующую трассировку (пример - GET / ping):
!!! uWSGI process 2988 got Segmentation Fault !!!
*** backtrace of 2988 ***
/usr/bin/uwsgi(uwsgi_backtrace+0x29) [0x46c8d9]
/usr/bin/uwsgi(uwsgi_segfault+0x21) [0x46ca61]
/lib64/libc.so.6() [0x38bf8329a0]
/usr/lib64/libpython2.6.so.1.0(PyObject_Call+0x3a) [0x38c2c43c4a]
/usr/lib64/libpython2.6.so.1.0(PyEval_CallObjectWithKeywords+0x43) [0x38c2ccfc93]
/usr/bin/uwsgi(python_call+0x1f) [0x47a0bf]
/usr/bin/uwsgi(uwsgi_request_wsgi+0x132) [0x47c602]
/usr/bin/uwsgi(wsgi_req_recv+0x92) [0x420352]
/usr/bin/uwsgi(simple_loop_run+0xc5) [0x464265]
/usr/bin/uwsgi(uwsgi_ignition+0x254) [0x468074]
/usr/bin/uwsgi(uwsgi_worker_run+0x330) [0x468400]
/usr/bin/uwsgi(uwsgi_run+0x3e5) [0x468865]
/lib64/libc.so.6(__libc_start_main+0xfd) [0x38bf81ed1d]
/usr/bin/uwsgi() [0x41d189]
*** end of backtrace ***
DAMN ! worker 2 (pid: 2988) died :( trying respawn ...
Respawned uWSGI worker 2 (new pid: 3003)
Я думаю, что самое интересное, что если я удалю все остальные точки монтирования и, например, оставлю только
mount = /ping=ping.py
все работает как положено. Чтобы убедиться, что эта ошибка не связана с нашим приложением, я также попробовал пример «Hello World», представленный на сайте uWSGI. Но поведение осталось прежним. Одна точка монтирования работает нормально, больше чем одна вызывает этот segfault.
Кроме того, как только я удалю настройку потоков thread = 2 (не с поддержкой потоков!) он также отлично работает с несколькими точками монтирования. Поэтому я подозреваю, что ошибка действительно ограничивается наличием нескольких точек монтирования в многопоточном режиме. И имейте в виду, он работает в рабочем режиме Apache MPM, поэтому я не ожидаю, что причиной является приложение (по крайней мере, не в этом случае: D)
Хотелось бы разобраться в этом, поскольку это было бы нечестным сравнением между узлами Apache и узлами nginx / uwsgi, если бы только Apache мог работать с многопоточностью, верно?
Если вам нужна дополнительная информация, дайте мне знать, и мы с радостью ее предоставим. Спасибо за любые советы или идеи, и просто за то, что вы дочитали до этого места, вы уже являетесь повседневным героем форума ;-)
Привет, Ральф
Попробуйте этот патч
но подумайте дважды, прежде чем следовать такому подходу. Наличие нескольких приложений в одном адресном пространстве процесса может выглядеть круто, но рано или поздно вы заплатите за неоптимальную реализацию (слишком много угловых случаев и обходных путей при использовании нескольких потоков с несколькими интерпретаторами в CPython)
Если это хорошо сработало в mod_wsgi, очень вероятно, что он будет работать и с uWSGI, но рассмотрите возможность разделения каждой точки монтирования в отдельном процессе.