Ответ 1
РЕДАКТИРОВАТЬ 1. Посмотрите, что у вас есть 1 виртуальное ядро, добавив комментарий во всех релевантных точках.
РЕДАКТИРОВАТЬ 2 Дополнительная информация от Maverick, поэтому я устраняю идеи, исключающие и разрабатывающие подтвержденные проблемы.
РЕДАКТИРОВАТЬ 3 Заполняется более подробная информация о параметрах очереди uwsgi и параметрах масштабирования. Улучшенная грамматика.
EDIT 4 Обновления от Maverick и незначительные улучшения
Комментарии слишком малы, вот некоторые мысли:
- Среднее значение нагрузки - это, в основном, сколько процессов работает или ждет внимания ЦП. Для совершенно загруженной системы с 1 центральным процессором среднее значение нагрузки должно быть 1,0; для четырехъядерной системы это должно быть 4.0. В тот момент, когда вы запускаете веб-тест, потоковые ракеты, и у вас много процессов, ожидающих процессор. Если средняя загрузка не превышает количество ядер ЦП с существенным запасом, это не проблема
- Первое значение "Время на запрос" 4s коррелирует с длиной очереди запросов - 1000 запросов, сбрасываемых на Django, почти мгновенно и заняли в среднем 4 секунды для обслуживания, около 3.4 из которых ожидали в очереди. Это связано с очень сильным несоответствием между количеством запросов (100) и количеством процессоров (16), в результате чего 84 из запросов ожидали процессор в любой момент.
-
Запуск при concurrency из 100, тесты занимают 41 секунду при 24 запросах в секунду. У вас есть 16 процессов (потоков), поэтому каждый запрос обрабатывается около 700 мс. Учитывая ваш тип транзакции, это длительное время для каждого запроса. Это может быть связано с тем, что:
-
Стоимость процессора для каждого запроса высока в Django (что маловероятно, учитывая низкое значение ЦП с панели инструментов отладки) - ОС - это многозадачная задача (особенно, если средняя нагрузка выше 4-8), а латентность сводится к слишком большому количеству процессов.
-
Недостаточно соединений DB, обслуживающих 16 процессов, поэтому процессы ждут, когда они будут доступны. У вас есть хотя бы одно соединение для каждого процесса? -
Существует значительная латентность вокруг БД, либо:-
Десятки небольших запросов, каждый из которых принимает, скажем, 10 мс, большинство из которых являются сетевыми накладными расходами. Если да, можете ли вы ввести кэширование или уменьшить SQL-запросы на меньшее число. ИлиЗабастовкa > -
Одна или несколько запросов принимают 100 мс. Чтобы проверить это, выполните профилирование в БД. Если это так, вам нужно оптимизировать этот запрос.
-
-
-
Распределение между ценой центрального процессора и пользователя в системе необычно велико, хотя общий процессор низкий. Это означает, что большая часть работы в Django связана с ядром, например, с сетью или диском. В этом случае это могут быть сетевые затраты (например, получение и отправка HTTP-запросов, а также получение и отправка запросов в БД). Иногда это будет высоким из-за пейджинга. Если нет пейджинга, то вам, вероятно, не придется об этом беспокоиться.
- Вы настроили процессы на 16, но имеете средний уровень нагрузки
(насколько высоко вы не указали). В идеале вы всегда должны иметь хотя бы один процесс, ожидающий процессор (так что процессоры не вращаются без движения). Процессы здесь не связаны с CPU, но имеют значительную задержку, поэтому вам нужно больше процессов, чем ядер. На сколько больше? Попробуйте запустить uwsgi с различным количеством процессоров (1, 2, 4, 8, 12, 16, 24 и т.д.), Пока у вас не будет лучшей пропускной способности. Если вы измените латентность среднего процесса, вам нужно будет снова настроить его. - Уровень 500 concurrency определенно является проблемой
, но является ли это клиентом или сервером? В отчете говорится, что 50 (из 100) имели неправильную длину контента, что подразумевает проблему с сервером. Кажется, что не-2xx указывает там. Возможно ли захватить ответы не-2xx для отладки - трассировки стека или конкретное сообщение об ошибке было бы невероятно полезно(EDIT) и вызвано очередью запросов uwsgi, для которой установлено значение по умолчанию 100.
Итак, вкратце:
- Django кажется прекрасным
- Несоответствие между concurrency теста нагрузки (100 или 500) по сравнению с процессами (16): вы вызываете слишком много параллельных запросов в систему для количества обрабатываемых процессов. Когда вы превысите количество процессов, все, что произойдет, это то, что вы удлиняете очередь HTTP-запросов на веб-сервере.
-
Существует большая задержка, поэтому либо
-
Несоответствие между процессами (16) и ядрами ЦП (1): если среднее значение нагрузки равно > 3, то, вероятно, слишком много процессов. Повторите попытку с меньшим количеством процессов.
-
Среднее значение нагрузки > 2 → попробуйте 8 процессов -
Среднее значение нагрузки > 4 → попробуйте 4 процесса - Среднее значение нагрузки > 8 → попробуйте 2 процесса
-
-
Если среднее значение нагрузки < 3, оно может быть в БД, поэтому необходимо профилировать БД, чтобы увидеть, есть ли множество небольших запросов (аддитивно вызывающих задержку) или один или два оператора SQL проблема
-
- Не записывая неудавшийся ответ, я не могу сказать о неудачах при 500 concurrency
Разработка идей
Средние значения нагрузки > 10 на одной порошковой машине действительно неприятны и (как вы заметили) приводят к большому переключению задач и обычному медленному поведению. Я лично не помню, как машина со средним значением нагрузки 19 (что у вас есть для 16 процессов) - поздравления за то, что она так высока;)
Производительность базы данных велика, поэтому я бы сразу дал понять, что сейчас.
Пейджинг. Чтобы ответить на вопрос о том, как увидеть пейджинг, вы можете обнаружить подкачку ОС несколькими способами. Например, в верхней части заголовок имеет вставки и выходы (см. Последнюю строку):
Processes: 170 total, 3 running, 4 stuck, 163 sleeping, 927 threads 15:06:31 Load Avg: 0.90, 1.19, 1.94 CPU usage: 1.37% user, 2.97% sys, 95.65% idle SharedLibs: 144M resident, 0B data, 24M linkedit. MemRegions: 31726 total, 2541M resident, 120M private, 817M shared. PhysMem: 1420M wired, 3548M active, 1703M inactive, 6671M used, 1514M free. VM: 392G vsize, 1286M framework vsize, 1534241(0) pageins, 0(0) pageouts. Networks: packets: 789684/288M in, 912863/482M out. Disks: 739807/15G read, 996745/24G written.
Количество процессов. В вашей текущей конфигурации количество процессов слишком велико. Масштабировать количество процессов до 2. Мы можем добавить это значение позже, в зависимости от изменения дополнительной нагрузки с этого сервера.
Расположение теста Apache Benchmark. Среднее значение нагрузки 1,85 для одного процесса подсказывает мне, что вы используете генератор нагрузки на том же компьютере, что и uwsgi, - это правильно?
Если это так, вам действительно нужно запустить это с другой машины, иначе тестовые прогоны не будут представлять фактическую нагрузку - вы берете память и процессор из веб-процессов для использования в генераторе нагрузки. Кроме того, генераторы 100 или 500 генератора нагрузки обычно усиливают ваш сервер таким образом, который не происходит в реальной жизни. На самом деле это может быть причиной того, что весь тест не удался.
Расположение базы данных. Среднее значение нагрузки для одного процесса также предполагает, что вы используете БД на той же машине, что и веб-процессы, - это правильно?
Если я правильно отношусь к БД, то первым и лучшим способом начать масштабирование является перемещение БД на другую машину. Мы делаем это по двум причинам:
-
Серверу БД требуется другой профиль оборудования из обработки node:
- Диск: БД требует много быстрого, резервного, резервного диска, а для обработки node нужен только базовый диск
- Процессор: для обработки node нужен самый быстрый процессор, который вы можете себе позволить, в то время как машина БД может обойтись без (часто ее производительность защищена на диске и ОЗУ).
- ОЗУ: машине БД обычно требуется как можно больше ОЗУ (и самый быстрый БД имеет все свои данные в ОЗУ), тогда как для многих узлов обработки требуется намного меньше (для вас требуется около 20 МБ на процесс - очень мало
- Масштабирование: Атомные БД наилучшим образом масштабируются благодаря наличию машин-монстров со многими процессорами, тогда как веб-уровень (не имеющий состояния) может масштабироваться путем подключения многих идентичных маленьких коробок.
-
Сродство к процессору: лучше, чтобы процессор имел среднюю нагрузку 1,0 и процессы имели сродство к одному ядру. Это максимизирует использование кэша процессора и минимизирует накладные расходы на переключение задач. Разделив DB и обрабатывающие узлы, вы выполняете эту привязку в HW.
500 concurrency с исключениями. Очередь запросов на диаграмме выше не более 100 - если uwsgi получает запрос, когда очередь заполнена, запрос отклоняется с ошибкой 5xx. Я думаю, что это происходило в вашем тестовом эксперименте 500 concurrency - в основном очередь заполнялась первыми 100 или около того потоками, затем остальные 400 потоков выдавали оставшиеся 900 запросов и получали немедленные ошибки 5xx.
Чтобы обрабатывать 500 запросов в секунду, вам необходимо обеспечить две вещи:
- Размер очереди запросов настроен для обработки пакета: используйте аргумент
--listen
дляuwsgi
- Система может обрабатывать пропускную способность более 500 запросов в секунду, если 500 является нормальным условием, или бит ниже, если 500 является пиком. См. Примечания масштабирования ниже.
Я предполагаю, что uwsgi имеет очередь, установленную на меньшее число, чтобы лучше справляться с DDoS-атаками; если они находятся под огромной нагрузкой, большинство запросов немедленно терпят неудачу с почти никакой обработкой, позволяющей блоку в целом по-прежнему реагировать на администраторов.
Общие рекомендации по масштабированию системы
Самое важное для вас, вероятно, для максимизировать пропускную способность. Еще одна возможная необходимость минимизировать время отклика, но я не буду обсуждать это здесь. При максимальной пропускной способности вы пытаетесь максимизировать систему, а не отдельные компоненты; некоторые локальные сокращения могут улучшить общую пропускную способность системы (например, изменение, которое происходит для добавления задержки в веб-уровне, чтобы повысить производительность БД, является чистым коэффициентом усиления).
В зависимости от специфики:
- Переместить БД на отдельный компьютер. После этого профилируйте БД во время теста нагрузки, запустив
top
и ваш любимый инструмент мониторинга MySQL. У вас должен быть профиль. Перемещение БД на отдельный компьютер приведет к некоторой дополнительной задержке (несколько мс) для каждого запроса, поэтому ожидайте немного увеличить количество процессов на уровне веб-страниц, чтобы поддерживать такую же пропускную способность. - Убедитесь, что очередь запросов
uswgi
достаточно велика, чтобы обрабатывать пакет трафика с использованием аргумента--listen
. Это должно быть в несколько раз максимальным запросом в секунду, который может обрабатывать ваша система. -
На уровне web/app: Баланс количества процессов с количеством ядер процессора и присущей латентности в этом процессе. Слишком много процессов замедляет производительность, слишком мало означает, что вы никогда не будете полностью использовать системные ресурсы. Не существует фиксированной точки балансировки, так как каждое приложение и шаблон использования различны, поэтому сравнивайте и настраивайте. В качестве руководства используйте задержку процессов, если каждая задача имеет:
- 0% латентности, тогда вам нужно 1 процесс на ядро
- 50% латентность (т.е. время процессора составляет половину фактического времени), тогда вам нужно 2 процесса на ядро
- Задержка 67%, тогда вам нужно 3 процесса на ядро.
-
Проверяйте
top
во время теста, чтобы убедиться, что вы используете загрузку процессора выше 90% (для каждого ядра), и средняя нагрузка немного выше 1.0. Если среднее значение нагрузки выше, отмените процесс. Если все будет хорошо, в какой-то момент вы не сможете достичь этой цели, и теперь БД может стать узким местом - В какой-то момент вам понадобится больше энергии в веб-уровне. Вы можете либо добавить к процессору больше процессора (относительно легко), и поэтому добавить больше процессов, и/или, которые вы можете добавить в большее количество узлов обработки (горизонтальная масштабируемость). Последнее может быть достигнуто в uwsgi, используя описанный метод здесь Łukasz Mierzwa