Почему работа не распределяется между работниками gunicorn равномерно?

#scheduling #gunicorn #round-robin

#планирование #gunicorn #круговой отбор #циклический перебор

Вопрос:

Я запускаю свое большое общедоступное веб-приложение. Это внутренний HTTP-сервер python, который отвечает на тысячи HTTP-запросов в минуту. Он написан с помощью Flask amp; SQLAlchemy. Приложение, работающее на EC2 в AWS. Тип экземпляра — c3.2xlarge (в нем 8 процессоров).

Я использую Gunicorn в качестве своего веб-сервера. В Gunicorn 17 рабочих процессов и 1 главный процесс. Ниже вы можете увидеть 17 работников gunicorn:

 $ sudo ps -aefF | grep gunicorn | grep worker | wc -l
17

$ sudo ps -aefF --sort -rss | grep gunicorn | grep worker
UID       PID  PPID  C      SZ     RSS PSR STIME TTY     TIME                           CMD
my-user 15708 26468  6 1000306 3648504   1 Oct06   ? 08:46:19 gunicorn: worker [my-service]
my-user 23004 26468  1  320150  927524   0 Oct07   ? 02:07:55 gunicorn: worker [my-service]
my-user 26564 26468  0  273339  740200   3 Oct04   ? 01:43:20 gunicorn: worker [my-service]
my-user 26562 26468  0  135113  260468   4 Oct04   ? 00:29:40 gunicorn: worker [my-service]
my-user 26558 26468  0  109946  159696   7 Oct04   ? 00:15:14 gunicorn: worker [my-service]
my-user 26556 26468  0  125294  148180   6 Oct04   ? 00:13:07 gunicorn: worker [my-service]
my-user 26554 26468  0  120434  128016   5 Oct04   ? 00:10:13 gunicorn: worker [my-service]
my-user 26552 26468  0   99233  116832   5 Oct04   ? 00:08:24 gunicorn: worker [my-service]
my-user 26550 26468  0   94334   96784   0 Oct04   ? 00:05:28 gunicorn: worker [my-service]
my-user 26548 26468  0   92865   90512   2 Oct04   ? 00:04:47 gunicorn: worker [my-service]
my-user 27887 26468  1   91945   86564   0 17:44   ? 00:02:57 gunicorn: worker [my-service]
my-user 26546 26468  0  127841   84464   5 Oct04   ? 00:03:39 gunicorn: worker [my-service]
my-user 26544 26468  0   90290   80736   2 Oct04   ? 00:03:12 gunicorn: worker [my-service]
my-user 26540 26468  0  107669   78176   5 Oct04   ? 00:02:33 gunicorn: worker [my-service]
my-user 26542 26468  0   89446   76616   5 Oct04   ? 00:02:49 gunicorn: worker [my-service]
my-user 26538 26468  0   88056   72028   5 Oct04   ? 00:02:02 gunicorn: worker [my-service]
my-user 26510 26468  0  106046   70836   2 Oct04   ? 00:01:49 gunicorn: worker [my-service]
  

Я просматриваю журналы всех HTTP-запросов, поступивших за последние 7 дней. Я сгруппировал и суммировал запросы по идентификатору процесса, который вы можете увидеть в ps команде me выше. Ниже вы можете увидеть результирующий график.

Как вы можете видеть, 5 работников gunicorn выполняют почти 100% работы. Остальные 12 в основном простаивают. И из этих 5 один работник (PID # 15708) выполняет большую часть работы.

Почему это происходит? Я хотел бы понять алгоритм, который использует gunicorn для распределения работы среди своих работников. Это точно не круговой отбор? Где я могу увидеть стратегию, которую он использует, и как я могу ее настроить? Что может объяснить взлеты и падения на этом графике? (Например, PID # 332 выполнял наибольшую работу до 7 октября, когда он начал снижаться и был вытеснен ростом PID # 15708)

Было бы полезно четкое объяснение и / или ссылки на соответствующую документацию.

введите описание изображения здесь

Комментарии:

1. Каково среднее время отклика? Если я не ошибаюсь, 8 октября в среднем получается 11,5 rps, если это достаточно кратковременные запросы, тогда нагрузку может взять на себя пара рабочих. Также, согласно приведенному ниже вопросу, это просто работники синхронизации? Если нет, то это изменит то, с чем работает каждый работник.

2. Что такое rps? Это запросы в секунду? Я рассчитываю 14,1 запросов в секунду на 8 октября: (628929 150725 7317 7949 11581 13532 13972 84253 285848 14405) / (60 * 60 * 24). За время, показанное на графике, среднее время отклика составило 0,041 секунды. Класс рабочих — это gevent_pywsgi .

3. Должно быть, я пропустил число при их сложении, извините. Но да, это то, что это запросы в секунду. Пара рабочих могла бы легко справиться с этим, исходя из рассматриваемой нами шкалы времени. Вероятно, из-за сбоев в запросах используются другие.

Ответ №1:

Согласно документации:

Синхронные рабочие по умолчанию предполагают, что ваше приложение ограничено ресурсами с точки зрения процессора и пропускной способности сети.

И:

Gunicorn полагается на операционную систему, обеспечивающую всю балансировку нагрузки при обработке запросов.

Основываясь на этих двух утверждениях, я бы сказал, что один работник, выполняющий большую часть работы, вряд ли когда-либо ограничен ресурсами. Как только ресурсы ограничены, четырех других работников достаточно, чтобы справиться с дополнительной нагрузкой без необходимости вызывать других.

Вероятно, вы можете безопасно уменьшить количество работников ( (2 x num cores) 1 это только начальная рекомендация). Это уменьшит вероятность перегрузки ресурсов и может повысить производительность вашего приложения.

Комментарии:

1. Класс рабочих gevent_pywsgi — это не синхронные рабочие по умолчанию. Когда они говорят «ограниченные ресурсы», что именно это означает? Мне также неясно, что значит сказать «ОС обеспечивает всю балансировку нагрузки». Означает ли это, что когда задание находится в ожидании, работник, который его принимает, определяется операционной системой, полностью независимой от кода и конфигурации gunicorn?