Что произойдет, если я начну слишком много фоновых заданий?

13

Мне нужно поработать на 700 сетевых устройствах, используя ожидаемый скрипт. Я могу сделать это последовательно, но пока время выполнения составляет около 24 часов. Это происходит в основном из-за времени, которое требуется для установления соединения, и задержки на выходе этих устройств (старых). Я могу установить два соединения и заставить их работать параллельно, но как далеко я могу это продвинуть?

Я не думаю, что я мог бы сделать все 700 из них одновременно, конечно, есть ограничение на нет. из соединений telnet моя ВМ может управлять.

Если бы я попытался запустить 700 из них в какой-то цикл вроде этого:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

С

  • ЦП 12 ЦП x Intel (R) Xeon (R) CPU E5649 @ 2,53 ГГц

  • Память 47,94 ГБ

Мой вопрос:

  1. Могут ли все 700 экземпляров работать одновременно?
  2. Как далеко я могу пройти, пока мой сервер не достигнет своего предела?
  3. Когда этот лимит будет достигнут, будет ли он ждать начала следующей итерации fooили произойдет сбой коробки?

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

KuboMD
источник
3
Я имел удачу parallel, используя около 50 одновременных заданий. Это отличная середина между параллелизмом от 1 до 700. Еще одна приятная вещь - это то, что она не имеет партии. Одно остановленное соединение остановится только само по себе, а не любое другое. Основным недостатком является управление ошибками. Ни один из этих подходов на основе оболочки не будет корректно обрабатывать ошибки. Вам придется самостоятельно проверять успешность и делать свои собственные повторные попытки.
Адам
1
Ваша очередь задач может быть 700 сегодня, но может ли размер увеличиться? Следите за расширением пространства подкачки - это означает, что вы достигли предела памяти. И процессор% не является хорошей мерой (для linux / unix), лучше учитывать среднюю нагрузку (длина очереди выполнения).
ChuckCottrill
1
Самым недавним способом, с помощью которого я прервал производство на своей все еще довольно новой работе, был случайный запуск миллиона плюс кратковременных фоновых заданий одновременно. В них принимали участие виртуальные машины Java (ожидание, ожидание опускало вилы), поэтому последствия были «ограничены» сотнями тысяч файлов отчетов об ошибках, которые нельзя было запустить.
michaelb958 - GoFundMonica,
1
@KuboMD И до тех пор, пока никто не захочет использовать ваш код.
10

Ответы:

17

Могут ли все 700 экземпляров работать одновременно?

Это зависит от того, что вы подразумеваете под одновременно. Если мы привередливы, то нет, они не смогут, если у вас в системе не будет 700 потоков выполнения, которые вы можете использовать (так что, вероятно, нет). Реально, хотя, да, они, вероятно, могут, если у вас достаточно оперативной памяти и / или пространства подкачки в системе. UNIX и его различные дети замечательно хороши в управлении огромными уровнями параллелизма, поэтому они так популярны для крупномасштабного использования высокопроизводительных вычислений.

Как далеко я могу пройти, пока мой сервер не достигнет своего предела?

На это невозможно ответить конкретно, не имея намного больше информации. В общем, вам нужно иметь достаточно памяти, чтобы встретиться:

  • Все требования к памяти во время выполнения одной работы, раз 700.
  • Требования к памяти bash для управления таким количеством заданий (bash не так уж и страшен, но управление заданиями не совсем эффективно использует память).
  • Любые другие требования к памяти в системе.

Предполагая, что вы встречаете это (опять же, только с 50 ГБ ОЗУ, вы все равно должны иметь дело с другими проблемами:

  • Сколько процессорного времени будет потрачено bash на управление заданиями? Вероятно, не так много, но с сотнями рабочих мест, это может быть значительным.
  • Какая пропускная способность сети потребуется? Простое открытие всех этих подключений может затопить вашу сеть на пару минут в зависимости от вашей пропускной способности и задержки.
  • Многие другие вещи, о которых я, вероятно, не подумали.

Когда этот лимит будет достигнут, будет ли он ждать начала следующей итерации с foo, или произойдет сбой коробки?

Это зависит от того, какой предел достигнут. Если это память, что-то умирает в системе (точнее, убивается ядром при попытке освободить память), или сама система может аварийно завершить работу (нет ничего необычного в том, чтобы настроить системы на преднамеренное падение при исчерпании памяти). Если это процессорное время, оно будет продолжать работать без проблем, просто невозможно будет многое сделать в системе. Если это сеть, вы можете привести к сбою других систем или служб.


Что вам действительно нужно, так это не запускать все задания одновременно. Вместо этого разделите их на пакеты и запустите все задания в пакете одновременно, дайте им закончить, а затем запустите следующий пакет. Для этого можно использовать GNU Parallel ( https://www.gnu.org/software/parallel/ ), но он менее чем идеален в таких масштабах в производственной среде (если вы используете его, не становитесь слишком агрессивными, как я уже сказал, вы можете затопить сеть и повлиять на системы, которые иначе вы бы не затронули). Я действительно рекомендовал бы поискать подходящий инструмент сетевой оркестровки, такой как Ansible ( https://www.ansible.com/), поскольку это не только решит ваши проблемы параллелизма (Ansible автоматически выполняет пакетирование, как я уже упоминал выше), но и предоставит вам множество других полезных функций (например, идемпотентное выполнение задач, хорошие отчеты о состоянии и встроенная интеграция с очень большое количество других инструментов).

Остин Хеммелгарн
источник
Существуют способы запуска ограниченного числа фоновых задач (с использованием bash, perl, python и др.), Отслеживания выполнения задач и выполнения большего количества задач по мере выполнения предыдущих задач. Простым подходом будет сбор пакетов задач, представленных файлами в подкаталогах, и обработка пакета за раз. Есть и другие способы ...
ЧакКоттрилл
Включает ли это также Unix-подобные системы? А что такое "GUN параллель"?
Biswapriyo
2
@ChuckCottrill Да, действительно, есть и другие способы сделать это. Однако, учитывая мой собственный опыт работы с подобными вещами, почти всегда лучше просто получить реальный инструмент оркестровки, чем пытаться развернуть свое собственное решение, особенно когда вы пройдете несколько десятков систем с точки зрения масштаба.
Остин Хеммельгарн
3
@forest Да, вы можете использовать rlimits для предотвращения сбоев системы, но получить их правильно в случае, подобном этому, нелегко (вам нужно заранее знать, какие требования к ресурсам для выполнения задач) и не защищать остальной части сети от любого воздействия, которое могут оказать эти задания (что, возможно, является гораздо более серьезной проблемой, чем сбой локальной системы).
Остин Хеммельгарн
12

Трудно сказать, сколько именно экземпляров можно запустить в качестве фоновых заданий, как вы описали. Но обычный сервер может поддерживать 700 одновременных подключений, если вы делаете это правильно. Веб-серверы делают это все время.

Могу ли я предложить вам использовать GNU параллельно ( https://www.gnu.org/software/parallel/ ) или что-то подобное для достижения этой цели? Это даст вам ряд преимуществ по отношению к фоновой работе:

  • Вы можете легко изменить количество одновременных сеансов.
  • И он будет ждать завершения сеансов, прежде чем начнет новые.
  • Это проще прервать.

Посмотрите здесь для быстрого начала: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source

laenkeio
источник
1
Интересный! Я посмотрю на это. Знаете ли вы, если попытка такого рода операций (без помощи Parallel) может привести к сбою гипервизора?
KuboMD
2
@KuboMD, если вы можете разбить гипервизор чем-то таким обыденным, это ошибка в гипервизоре :)
hobbs
Кроме того, веб-серверы часто используют многопоточность или обработку на основе событий (пример: gunicorn.org )
ChuckCottrill
10

Использование &для параллельной обработки хорошо при выполнении нескольких задач и при мониторинге прогресса. Но если вы работаете в корпоративной производственной среде, вам нужно что-то, что дает вам лучший контроль.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

Это будет работать fooдля каждого файла в ~/sagLogs. Он запускает задание каждые 0,5 секунды, он будет запускать как можно больше заданий параллельно, пока свободна ОЗУ 1 ГБ, но будет соблюдать ограничения в вашей системе (например, количество файлов и процессов). Как правило, это означает, что вы будете выполнять 250 заданий параллельно, если не отрегулировали количество разрешенных открытых файлов. Если вы отрегулируете количество открытых файлов, у вас не должно возникнуть проблем при параллельном запуске 32000 - если у вас достаточно памяти.

Если задание не выполнено (то есть возвращается с кодом ошибки), оно будет повторено 10 раз.

my.log скажет вам, если задание выполнено успешно (после повторных попыток) или нет.

Оле Танге
источник
Это выглядит очень многообещающе, спасибо.
KuboMD
Провел простое испытание cat ~/sagLogs/* >> ~/woah | parallelи святой моли, который был быстр. 1,054,552 строк в мгновение ока.
KuboMD
3
Команда, которую вы дали, имеет двойное перенаправление, поэтому я не думаю, что она делает то, что вы намеревались сделать. На GNU Parallel накладные расходы составляют 10 мс на одно задание, поэтому выполнение 1M заданий занимает порядка 3 часов.
Оле Танге
1
Это вообще не применимо, если все, что вы хотите сделать, это просто объединить файлы.
Оле Танге
1
@KuboMD - тривиальный цикл занятости процессора, с которым awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' можно поиграть. Или попробуйте выполнить задачу, например, sleep 10увидеть, как она работает nв полете, не тратя много времени на процессор. например, time parallel sleep ::: {100..1}бегать спит от 100 до 1 секунды.
Питер Кордес
1

Что произойдет, если я начну слишком много фоновых заданий?

система станет медленной и не отвечает, худший случай настолько не отвечает, что было бы лучше просто нажать кнопку питания и выполнить полную перезагрузку ... это будет запускать что-то от имени пользователя root, где у него была привилегия уйти с этим. Если ваш Баш скрипт работает в обычных привилегиях пользователя, то первое , что приходит на ум, /etc/security/limits.confи /etc/systemd/system.confи все переменные в нем [идеале говоря] предотвратить пользователь (ей) от перегрузки системы.

  • процессор = xeon E5649, то есть 12- ядерный процессор; Таким образом, у вас есть 12 ядер для 12 процессов, выполняемых одновременно, каждое из которых использует одно из двенадцати ядер на 100%. Если вы запустите 24 процесса, то каждый из них будет работать с 50% -ной загрузкой на каждом из двенадцати ядер, 700 процессов = 1,7%, но это компьютер, если все будет выполнено правильно за приемлемое количество времени, тогда это = успех; Быть эффективным не всегда актуально.

    1. Могут ли все 700 экземпляров работать одновременно? Конечно, 700 не так много; например, мой /etc/security/limits.conf по maxprocумолчанию равен 4 135 275

    2. Как далеко я могу пройти, пока мой сервер не достигнет своего предела? Я уверен, что намного дальше, чем 700.

    3. Ограничения ... что произойдет, если скрипт будет запущен под учетной записью пользователя [и, в целом, root, а также в limits.confзначительной степени относится ко всем], - это то, что скрипт просто завершится после попытки выполнить foo &700 раз; тогда вы ожидаете увидеть 700 процессов foo, каждый с разным pid, но вы можете увидеть только 456 (выбор случайного числа), а остальные 244 никогда не запускались, потому что они были заблокированы каким-то ограничением безопасности или системным ограничением.

Вопрос на миллион долларов: сколько вы должны запустить одновременно?

участвуя в работе сети, и вы сказали, что каждый из них будет устанавливать соединение с telnet, догадываясь о том, что вы столкнетесь с сетевыми ограничениями и накладными расходами, прежде чем начнете использовать ограничения ЦП и ОЗУ. Но я не знаю, что конкретно вы делаете, что, скорее всего, произойдет, если вы можете запустить все 700 одновременно, но все будет автоматически блокироваться, пока предыдущие процессы и сетевые подключения не завершатся и не закроются в зависимости от различных системных ограничений, или что-то вроде Первые 500 начнутся, а остальные 200 - нет, потому что ограничения системы или ядра мешают. Но как бы ни бегали сразу, будет немного сладковатогоместо, чтобы сделать все как можно быстрее ... минимизируя накладные расходы и повышая эффективность. Будучи 12 ядрами (или 24, если у вас 2 процессора), начните с 12 (или 24) сразу, а затем увеличивайте число одновременных партий на 12 или 24, пока не увидите улучшения во время выполнения.

Подсказка: Google Max Telnet подключений и посмотреть, как это относится к вашей системе (ам). Также не забывайте о брандмауэрах. Также выполните быстрый расчет памяти, необходимой для каждого процесса x 700; убедитесь, что <доступно ОЗУ (около 50 ГБ в вашем случае), иначе система начнет использовать SWAP и в основном перестанет отвечать на запросы. Таким образом, запускайте 12, 24, N процессов одновременно и следите за свободным объемом ОЗУ, затем увеличивайте N, уже имея некоторые знания о том, что происходит.

По умолчанию RHEL ограничивает количество соединений telnet с одного хоста до 10 одновременных сеансов. Это функция безопасности ... установите значение 10, /etc/xinetd.conf, измените значение per_source.

рон
источник