#python #multithreading #process #operating-system #uwsgi
Вопрос:
Итак, я начал работать с uWSGI для своего приложения на python всего два дня назад и пытаюсь понять различные параметры, которые мы указываем в .ini
файле. Вот как app.ini
в настоящее время выглядит мой файл:
# The following article was referenced while creating this configuration
# https://www.techatbloomberg.com/blog/configuring-uwsgi-production-deployment/
[uwsgi]
strict = true ; Only valid uWSGI options are tolerated
master = true ; The master uWSGI process is necessary to gracefully re-spawn and pre-fork workers,
; consolidate logs, and manage many other features
enable-threads = true ; To run uWSGI in multithreading mode
vacuum = true ; Delete sockets during shutdown
single-interpreter = true ; Sets only one service per worker process
die-on-term = true ; Shutdown when receiving SIGTERM (default is respawn)
need-app = true
;disable-logging = true ; By default, uWSGI has rather verbose logging. Ensure that your
;log-4xx = true ; application emits concise and meaningful logs. Uncomment these lines
;log-5xx = true ; if you want to disable logging
cheaper-algo = busyness
processes = 128 ; Maximum number of workers allowed
cheaper = 1 ; Minimum number of workers allowed - default 1
cheaper-initial = 2 ; Workers created at startup
cheaper-overload = 60 ; Will check busyness every 60 seconds.
cheaper-step = 3 ; How many workers to spawn at a time
auto-procname = true ; Identify the workers
procname-prefix = "rhs-svc " ; Note the space. uWSGI logs will be prefixed with "rhs-svc"
Когда я начинаю uWSGI
— вот что я вижу:
[uWSGI] getting INI configuration from app.ini
*** Starting uWSGI 2.0.19.1 (64bit) on [Thu Sep 30 10:49:45 2021] ***
compiled with version: Apple LLVM 12.0.0 (clang-1200.0.32.29) on 29 September 2021 23:55:27
os: Darwin-19.6.0 Darwin Kernel Version 19.6.0: Thu Sep 16 20:58:47 PDT 2021; root:xnu-6153.141.40.1~1/RELEASE_X86_64
nodename: sth-sth-sth
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 12
current working directory: /Users/sth.sth/My-Microservice
detected binary path: /Users/sth.sth/My-Microservice/venv/bin/uwsgi
your processes number limit is 2784
your memory page size is 4096 bytes
detected max file descriptor number: 10240
lock engine: OSX spinlocks
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :9000 fd 4
[busyness] settings: min=25%, max=50%, overload=60, multiplier=10, respawn penalty=2
uwsgi socket 0 bound to TCP address 127.0.0.1:57164 (port auto-assigned) fd 3
Python version: 3.9.6 (default, Jun 29 2021, 06:20:32) [Clang 12.0.0 (clang-1200.0.32.29)]
Python main interpreter initialized at 0x7fd32b905bf0
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 9403584 bytes (9183 KB) for 128 cores
*** Operational MODE: preforking ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fd32b905bf0 pid: 78422 (default app)
spawned uWSGI master process (pid: 78422)
spawned uWSGI worker 1 (pid: 78423, cores: 1)
spawned uWSGI worker 2 (pid: 78424, cores: 1)
spawned uWSGI http 1 (pid: 78425)
Я запускаю это на macOS Catalina с 6-ядерным процессором i7. Почему там написано detected cores: 12
, когда я только 6
что ? Он говорит process number limit: 2784
— могу ли я действительно приступить processes = 128
к processes = 2784
работе ? В документах упоминается, что processes = 2 * cpucores
это слишком простая метрика, чтобы ее придерживаться. Какие показатели я должен в идеале учитывать? В настоящее время мое приложение представляет собой оболочку (т. Е. Никакой бизнес — логики-пока только в памяти, я, по сути, создаю шаблон), и мы пока не ожидаем каких-либо интенсивных операций подключения к БД/ввода-вывода. Как мне определить, какое соотношение потоков и процессов является хорошим? Я прошу прощения, если мои вопросы слишком просты, но я очень новичок в этом
Ответ №1:
Ядра против процессоров
Прежде всего, количество ядер-это не обязательно количество процессоров. На ранних компьютерах это было похоже на 1-1, но с современными улучшениями один процессор может предложить более одного ядра. (Проверьте это: https://www.tomshardware.com/news/cpu-core-definition,37658.html). Таким образом, если он обнаружил 12 ядер, вы можете использовать его в качестве основы для своего исчисления.
Процессы WSGI
Количество процессов означает, сколько различных параллельных экземпляров вашего веб-приложения будет запущено на этом сервере. WSGI сначала создает главный процесс, который будет координировать действия. Затем он загружает ваше приложение и создает N его клонов (вилка). Эти дочерние разветвленные процессы изолированы, они не разделяют ресурсы. Если один процесс по какой-либо причине выходит из строя (например, проблемы с вводом-выводом), он может завершиться или даже быть добровольно убит основным процессом, в то время как остальные клоны продолжают работать, поэтому ваше приложение все еще работает. Когда процесс завершается/завершается, главный процесс может создать другой свежий клон для его замены (повторного появления).
Можно задать количество процессов как соотношение доступных ядер. Но нет никакой пользы в том, чтобы увеличивать его слишком сильно. Таким образом, вам определенно не следует устанавливать его на предел (2784). Помните, что операционная система будет циклически выполнять все процессы, чтобы дать каждому из них возможность обработать некоторые инструкции. Таким образом, если он предлагает 12 ядер и вы создаете около 1000 различных процессов, вы просто нагружаете систему, и в конечном итоге вы получите ту же пропускную способность (или даже худшую пропускную способность, поскольку в ней так много хаоса).
Количество потоков внутри процесса
Затем мы переходим к количеству потоков. Для простоты давайте просто скажем, что количество потоков означает количество параллельных запросов, которые может обработать каждый из этих дочерних процессов. В то время как один поток ожидает ответа базы данных на запрос, другой поток может делать что-то еще, чтобы ответить на другой запрос.
Вы можете сказать: зачем мне нужно несколько потоков, если у меня уже есть несколько процессов?
Процесс-дорогостоящая вещь, но потоки-это просто способ, с помощью которого вы можете параллелизировать рабочую нагрузку, с которой может справиться процесс. Представьте, что процесс-это кофейня, а потоки-это количество сотрудников, которые у вас внутри. Вы можете разместить 10 различных кофеен по всему городу. Если один из них закроется, есть еще 9, куда еще может пойти клиент. Но каждому магазину нужно определенное количество обслуживающего персонала, чтобы обслуживать людей наилучшим образом.
Как правильно установить эти цифры
Если вы задаете только один процесс со 100 потоками, это означает, что 100 — это ваш предел параллелизма. Если в какой-то момент к вашему приложению поступит 101 одновременный запрос, последнему из них придется дождаться завершения одного из 100 первых. Именно тогда вы начинаете получать увеличивающееся время отклика для некоторых пользователей. Чем больше запросов ставится в очередь, тем хуже становится (теория очередей).
Кроме того, поскольку у вас есть один процесс, если он выйдет из строя, все эти 100 запросов завершатся ошибкой сервера (500). Таким образом, разумнее иметь больше процессов, скажем, 4 процесса, обрабатывающих по 25 потоков каждый. У вас все еще есть ограничение на 100 параллелизмов, но ваше приложение более устойчиво.
Вам предстоит узнать ожидаемую нагрузку вашего приложения, чтобы вы могли правильно настроить эти цифры. Когда у вас есть внешние интеграции, такие как базы данных, вы также должны учитывать их ограничения. Допустим, сервер PostgreSQL, который может обрабатывать 100 одновременных подключений. Если у вас 10 процессов WSGI, по 40 потоков в каждом (с пулом подключений размером 40), то есть вероятность, что вы загружаете базу данных 400 подключениями, и тогда у вас возникает большая проблема, но это не ваш случай!
Итак, просто используйте предлагаемое количество процессов ( 12 * 2 = 24
) и установите столько потоков, сколько необходимо, чтобы обеспечить определенный желаемый уровень параллелизма.
Если вы не знаете ожидаемой нагрузки, я предлагаю вам провести своего рода тест производительности, который может имитировать запросы к вашему приложению, а затем вы можете поэкспериментировать с различными нагрузками и настройками и проверить наличие побочных эффектов.
Дополнительно: Контейнеры
Если вы запускаете приложение на платформе оркестровки контейнеров, такой как Kubernetes, то, вероятно, у вас может быть несколько сбалансированных контейнеров, обслуживающих одно и то же приложение. Вы даже можете сделать его динамичным, чтобы количество контейнеров увеличивалось, если объем памяти или обработки превышает пороговое значение. Это означает, что в дополнение ко всем этим тонким настройкам WSGI для одного сервера существуют также другие современные уровни конфигураций, которые могут помочь вам справиться с пиками и сценариями высокой нагрузки.
Комментарии:
1. Это было на самом деле ОЧЕНЬ полезно. Ваши примеры на самом деле дали мне больше ясности в том понимании, которое у меня было до сих пор. Теперь я чувствую себя гораздо увереннее в своих параметрах. Спасибо!