...

Планировщик CFS в Linux: функциональность и альтернативы в хостинге серверов

Планировщик CFS в Linux управляет тем, как серверные ядра распределяют свое время между процессами, и таким образом напрямую влияет на задержку, пропускную способность и справедливость при размещении серверов. В этом руководстве я расскажу о том, как он работает, о рычагах настройки и полезных альтернативах, таких как ULE, BFS и EEVDF для Хостинг с веб-серверы.

Центральные пункты

  • Справедливость и vruntime определяют, какая задача получит процессор.
  • Cgroups регулировать квоты и cpu.shares для изоляции клиентов.
  • Настройка ядра через sched_latency_ns и Зернистость.
  • Альтернативы такие как BFS, ULE, EEVDF для специальных Рабочие нагрузки.
  • ПрактикаСродство к ядру, планировщик ввода/вывода и Тесты комбайн.

Как CFS работает в повседневной жизни

С помощью Completely Fair Scheduler виртуальная среда выполнения решает, какая задача будет выполняться следующей, в результате чего ярмарка и предсказуемый Распределение создается. Каждая задача получает процессорное время пропорционально значению nice, так что при низком значении nice она получает больше долей. В хостинговых средах множество небольших веб-запросов, cronjobs и резервных копий распределяют CPU между собой, не позволяя одному процессу занимать все время. Интерактивные рабочие нагрузки, такие как запросы NGINX, выигрывают от частых коротких временных срезов, в то время как пакетные задачи получают более длинные блоки. Это означает, что время отклика остается надежным для пользователей, даже если многие сайты обрабатывают запросы параллельно.

Я использую группы Cgroups для ограничения клиентов и служб, поскольку cpu.shares и cpu.max обеспечивают четкое Итоговые показатели по акциям и трудно Лимиты. Значение по умолчанию 1024 доли для “нормальных” и 512 для “менее важных” распределяет ядра понятным образом. В параметре cpu.max, например, я установил 50 мс за период 100 мс, что фактически соответствует 50% доле процессора. Такая настройка обеспечивает предсказуемый резерв для хостинга рабочих нагрузок с переменной нагрузкой. Компактное объяснение этого принципа можно найти на сайте справедливое распределение процессора.

Механика CFS объясняется наглядно

По своей сути CFS управляет всеми готовыми к выполнению задачами в дереве "красное/черное", отсортированном по vruntime и с эффективным Выбор наименьшего виртуального времени выполнения. Эта задача запускается следующей и увеличивает свое виртуальное время выполнения пропорционально затраченному процессорному времени и взвешивается через значение nice. Это создает плавный баланс без жестких очередей, что обеспечивает чистые результаты, особенно при смешанной нагрузке. На многоядерных системах планировщик перемещает задачи между очередями выполнения, но при этом обращает внимание на локальность кэша через привязку к ядру. Таким образом, CFS сочетает балансировку нагрузки с минимальным количеством дорогостоящих миграций.

Для тонкой настройки такие параметры, как sched_latency_ns и sched_min_granularity_ns, задают курс для Латентность и Пропускная способность. Меньшие значения задержки благоприятствуют коротким интерактивным заданиям, в то время как большие значения усиливают пакетные задания. В тестах с помощью таких инструментов, как stress-ng и fio, я проверяю влияние на время отклика и загрузку процессора. С увеличением количества заданий возрастает и административная нагрузка на дерево, что может проявляться в виде пиковых задержек. Однако правильно установленные квоты и лимиты позволяют сдерживать эти эффекты в хостинговых средах.

Сильные стороны CFS в области размещения серверов

Самая большая сила заключается в Справедливость, равномерно и понятно Ресурсы распределенные. В средах с общим доступом это означает, что ни один клиент не вытесняет другого, поскольку квоты и доли четко определяют весовые коэффициенты. Интерактивные службы получают быстрое время отклика, а резервные копии могут выполняться без спешки. Расстановка приоритетов с помощью хороших значений дополняет эту картину и оставляет мне пространство для координации в зависимости от роли службы. Балансировка нагрузки на все ядра позволяет мне эффективно использовать доступную вычислительную мощность, не давая Джеффу отдельных потоков слишком много места.

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

Ограничения и типичные камни преткновения

При очень большом количестве одновременных задач накладные расходы на операции с деревом возрастают, чего не происходит в случае с Советы die Латентность может увеличить производительность. В хостингах с большим количеством очень коротких запросов иногда происходит частая смена контекста. Такое поведение “трэшинга” снижает эффективность, если значения гранулярности выбраны неверно. Меньшее количество, но более длинных временных срезов может помочь, если сохраняется интерактивность. CFS чутко реагирует на неправильные квоты, поэтому я постоянно проверяю лимиты с помощью нагрузочных тестов.

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

Сравнение альтернатив: ULE, BFS и EEVDF

Для особых рабочих нагрузок я рассматриваю альтернативные варианты, чтобы Латентность или Масштабирование По-разному расставляют приоритеты. В ULE используются более простые очереди, что позволяет снизить административные затраты, в BFS приоритет отдается быстроте реакции, что позволяет добиться успеха при небольшом количестве задач, а в EEVDF справедливое распределение сочетается с дедлайнами. В частности, EEVDF обещает меньшее время ожидания для интерактивных нагрузок, поскольку планировщик уделяет больше внимания “самому раннему допустимому сроку”. Для очень больших серверных полей в конечном итоге важно то, какое сочетание эффективности и планируемости действительно выигрывает в вашем собственном стеке. Структурированный взгляд на сильные и слабые стороны и области применения помогает в выборе.

планировщик Сложность Сильные стороны хостинга Слабые стороны Подходит для
CFS Высокий Справедливое распределение, Cgroups Пики задержки Общий хостинг, смешанная нагрузка
ULE Низкий Простые сигналы, низкий уровень Загрузить Меньше изоляции ВМ, HPC-подобные модели
BFS Средний Интерактивность, Скорость Слабое масштабирование Настольные компьютеры, небольшие серверы
EEVDF Средний Низкая задержка, сроки По-прежнему мало практики Современные стеки для хостинга

Настройка ядра: практические шаги для CFS

Для CFS я часто переключаю sched_autogroup_enabled=0, чтобы неявные группы не искажали изображение и Распределение нагрузки очистить остается. С помощью sched_latency_ns я предпочитаю начинать с 20 мс, что благоприятствует интерактивным сервисам, и настраивать sched_min_granularity_ns, чтобы усмирить изменения контекста. Значения зависят от профиля: многие короткие веб-запросы нуждаются в другой тонкой настройке, чем окна резервного копирования. Я тестирую изменения последовательно и измеряю перцентили, а не просто смотрю на средние значения. Это гарантирует, что не только средние значения будут выглядеть красиво, но и длинные очереди сократятся.

Если вы хотите более глубоко изучить параметры sysctl, вы найдете хорошее введение здесь: настройка sysctl. Я также настраиваю распределение IRQ, регулятор процессора и профили энергопотребления, чтобы процессор не переходил постоянно в экономичные состояния. Я использую регуляторы производительности для стеков с задержками, в то время как чисто пакетные коробки живут со сбалансированным контролем. Я четко разделяю этапы тестирования и производства, чтобы не было сюрпризов. После каждого этапа я проверяю журналы и метрики, прежде чем двигаться дальше.

Разумно используйте cgroups и квоты

С помощью cpu.shares я назначаю относительные Вес в то время как cpu.max является жестким Границы наборы. Клиент с 512 долями получает вдвое меньше вычислительного времени, чем клиент с 1024 долями, если оба генерируют нагрузку в одно и то же время. Я использую cpu.max для четкого ограничения пиков, например 50 мс за 100 мс. Для выделенных заданий стоит использовать cpuset.cpus, чтобы служба использовала фиксированные ядра и кэш оставался теплым. В целом, это приводит к устойчивому разделению между клиентами и сервисами.

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

Практика: Веб-сервер и базы данных под управлением CFS

Управляемые событиями веб-серверы сокращают количество переключений контекста и гармонично сочетаются с CFS, что приводит к заметному снижению времени Время реагирования и лучше Масштабирование сгенерирован. В тестах я вижу, что NGINX поддерживает более высокую скорость запросов с меньшим джиттером на том же оборудовании. Базы данных положительно реагируют на привязку к ядру, когда фоновые задания держатся подальше от горячих ядер. Помогают простые правила: Web на ядрах A-B, batch на C-D и DB на E-F. Таким образом, стек сохраняет конвейер чистым, а кэши - теплыми.

Много маленьких рабочих PHP FPM вызывают слишком много переключений при агрессивной гранулярности. Тогда я увеличиваю минимальный временной срез и проверяю, остается ли время отклика стабильным. В то же время я дросселирую болтливые журналы, чтобы ввод-вывод не стал тормозом. Основой здесь служит CFS, но пик производительности достигается за счет тонкой настройки всего стека. Таким образом, все шестеренки сцепляются друг с другом, не заставляя хостера задерживать дыхание.

Ввод/вывод памяти и планирование работы процессора: взаимодействие

Планировщик процессора и планировщик ввода-вывода влияют друг на друга, поэтому гармоничная настройка может заметно улучшить ситуацию. Преимущества на сайте Латентность приносит. Для NVMe я обычно использую Noop или mq-deadline, а для HDD mq-deadline лучше справляется с длинными очередями. Если процессор выделяет время вовремя, но путь ввода-вывода застопоривается, общий эффект сводится на нет. Поэтому я проверяю планировщик ввода-вывода параллельно с параметрами CFS. Обзор Noop, mq-deadline и BFQ я привожу здесь: Планировщик ввода/вывода в сравнении.

Для узлов баз данных я настраиваю глубину очереди и опережающее чтение, чтобы запланированные CFS слоты не пропадали из-за блокировки ввода-вывода. Для веб-серверов с большим количеством мелких файлов важна низкая задержка в стеке ввода-вывода. В сценариях виртуализации я полагаюсь на согласованные планировщики на хосте и госте, чтобы избежать непредсказуемых шаблонов. Именно так планировщик процессора взаимодействует с подсистемой хранения. В конечном итоге важна последовательная цепочка от запроса до ответа.

Балансировка SMP, сродство ядер и NUMA

Я направляю потоки на фиксированные ядра, чтобы Кэши теплые и миграционные расходы маленький остаются. Для хостов NUMA я связываю память и процессор вместе, поскольку удаленный доступ к памяти увеличивает задержки. CFS балансирует нагрузку между очередями выполнения, но сознательные правила сродства часто дают больший эффект. Службы с частым доступом к кэшу выигрывают от стабильных групп ядра. Пакетным заданиям разрешено перемещаться, пока они не мешают горячим ядрам.

На практике я устанавливаю параметры cpuset.cpus и numactl, а затем проверяю время запросов и количество пропусков процессора. Чем меньше ненужных миграций, тем лучше время отклика. Я также оцениваю распределение прерываний, чтобы жесткие пики IRQ не забивали ядро. Таким образом, я добиваюсь плавной синхронизации важных потоков. Это спокойствие окупается общей производительностью стека.

Групповое планирование: приятное, взвешенное и иерархическое

Частым камнем преткновения в хостинге является Взаимодействие между хорошо-Приоритеты и Весовые коэффициенты группы. CFS сначала справедливо распределяет между группами, а затем внутри группы между задачами. Это означает, что процесс с nice -5 может получить меньше процессора, чем другой с nice 0, если его группа (клиент/контейнер) имеет меньший вес. Поэтому для получения стабильных результатов я сначала устанавливаю Весовые коэффициенты групп и используйте nice только для тонкой настройки внутри сервиса.

На практике я работаю с несколькими четкими уровнями (например, 512/1024/2048 долей для “низкого/нормального/высокого”) и документирую, какие службы работают в той или иной группе. Это позволяет сохранить Справедливость прослеживается в иерархии. Тем, кто много работает с недолговечными процессами (например, заданиями CGI/CLI), также полезно на основе групп контроль, поскольку в противном случае волатильные задачи будут непреднамеренно обходить групповой корсет. Я регулярно использую метрики времени выполнения, чтобы проверить, соответствует ли внутреннее распределение профилю нагрузки.

Контейнеры и оркестровка: запросы, лимиты и дросселирование

В контейнерных средах “запрос” обычно обозначает относительный вес (доли/вес), “лимит” на Квота (cpu.max). Взаимодействие решает Дросселирование: Если квота слишком жесткая, процессор контейнера замедляется в течение периода - это видно по скачкам задержки p95/p99. Поэтому я устанавливаю квоты таким образом, чтобы нормальные всплески укладывались в этот период и сервисы редко подвергались жесткому дросселированию. Там, где это возможно, я использую Всплеск-резерв (например, cpu.max.burst), чтобы смягчить короткие пики без искажений.

Важно не устанавливать слишком низкие запросы: Если вес будет слишком мал, интерактивные сервисы будут отставать от пакетного шума. Я калибрую запросы на основе измеренной базовой нагрузки и безопасных лимитов таким образом, чтобы Бюджеты ошибок поддерживаются в пиковое время. Для многопользовательских узлов я также планирую буферные ядра, чтобы пики нагрузки на отдельные контейнеры не влияли на соседние.

Методы измерения и устранение неполадок в контексте планировщика

Я никогда не оцениваю настройку CFS вслепую, а измеряю ее целенаправленно. Я использую для обзора:

  • Длина очереди выполнения на один процессор (нагрузка по сравнению с активными ядрами),
  • Изменение контекста в секунду и количество потоков,
  • Кража процессора и SoftIRQ-шары,
  • Процент времени отклика (p50/p95/p99),
  • Распределение vruntime или задержки при планировании.

Если возникают пики задержки, я сначала ищу Дросселирование (квота исчерпана), затем после Миграции (холодный кэш) и, наконец, после Блокировка ввода/вывода (глубина очереди, насыщенность хранилища). Я смотрю на шаблоны пробуждения: частые короткие пробуждения многих рабочих указывают на слишком мелкую детализацию или болтливый ввод-вывод. Повышенная доля ksoftirqd на ядре указывает на горячие очереди IRQ - в этом случае я распределяю IRQ и активирую RPS/XPS, чтобы нагрузка на сеть распределялась более широко.

Классы в реальном времени, предварительное оповещение и контроль тиков

Помимо CFS, существуют следующие классы реального времени SCHED_FIFO/RR. Они перекрывают CFS: неправильно настроенный RT-поток может буквально выпустить воздух из системы. Поэтому я назначаю RT-Prio только очень выборочно (например, для аудио/телеметрии) и определяю четких наблюдателей. Для хостинга обычно достаточно CFS с чистыми весами.

На ПреемственностьВыбор модели вытеснения (например, “добровольное” или “полное/динамическое вытеснение”) меняет соотношение задержка/пропускная способность. Для веб-стеков я предпочитаю большее количество вытеснений, для чисто пакетных хостов - меньшее. Оптимизация тиков (nohz-modes) могут уменьшить джиттер, но их следует использовать с осторожностью. На изолированных ядрах я иногда комбинирую nohz_full и Affinity, чтобы горячие потоки работали как можно меньше - важно, чтобы нагрузка на систему и IRQ случайно не переместилась на эти ядра.

Виртуализация: KVM, пиннинг vCPU и кража времени

В среде гипервизора планировщик хоста определяет, когда виртуальные процессоры может работать. Создайте избыточное бронирование Время кражи в гостях, что действует как “невидимая задержка”. Для арендаторов, критичных к задержкам, я привязываю vCPU к физическим ядрам и поддерживаю умеренный overcommit. Я также отделяю потоки эмулятора (IO threads, vhost) от горячих ядер гостей, чтобы они не мешали друг другу.

Я избегаю двойного дросселирования: если гость уже использует cpu.max, я не устанавливаю дополнительные жесткие квоты на хосте для той же рабочей нагрузки. Контроль частоты остается задачей хоста; гости получают косвенную выгоду, если регулятор хоста чисто масштабируется в зависимости от фактической рабочей нагрузки. Для равномерных задержек я считаю, что стабильность за пределами чистой максимальной частоты важнее, чем пиковая частота на бумаге.

AutoNUMA, локализация памяти и THP

NUMA может быть как выигрышем в производительности, так и ловушкой. AutoNUMA часто помогает, но может создавать дополнительные накладные расходы при интенсивном перемещении потоков. В хостинговых стеках с четкими границами сервисов я связываю CPU и Память (cpuset.cpus и cpuset.mems) вместе. Это означает, что горячие данные остаются локальными и CFS приходится компенсировать меньшее количество миграций.

Большие страницы (THP) снижают давление на TLB, но подходят не для всех профилей. Для баз данных “madvise” может иметь больше смысла, чем “always”. Блокирующие ошибки страниц сильно влияют на интерактивную задержку; поэтому я планирую буферы (страничный кэш, общий буфер) так, чтобы слоты CFS использовались продуктивно и не ждали событий ввода-вывода или MMU. Это можно измерить с помощью частоты ошибок страниц и кривых промахов кэша.

Сетевой путь: управление IRQ, RPS/XPS и опрос занятости

Во многих веб-нагрузках преобладают сетевые карты. Я распределяю IRQ-очереди сетевой карты по нескольким ядрам и сохранять их аффинный рабочим потокам, чтобы пробуждения оставались локальными. RPS/XPS помогает устранить горячие точки SoftIRQ, если отдельные очереди RX/TX несут слишком большую нагрузку. Если ksoftirqd становится заметно горячим, это указывает на переполнение SoftIRQ - тогда я выравниваю потоки и увеличиваю параметры бюджета, если это необходимо, без потери справедливости.

Дополнительный опрос может иметь смысл в особых настройках с низкой задержкой, но он требует затрат процессорного времени. Я использую его редко и только в том случае, если могу доказать с помощью измерений, что p99 значительно падает, не нагружая хост в целом. Как правило, чистое сродство IRQ, Cgroups и гранулярность CFS обеспечивают лучшее соотношение затрат и результатов.

Outlook: От CFS к EEVDF и подходам к пользовательскому пространству

EEVDF расширяет справедливое распределение, включая крайние сроки, что заметно более короткий и более предсказуемым Ответы обещания. Особенно в случае интерактивных целей с задержками это может иметь значение. Я внимательно слежу за версиями ядра и тестирую EEVDF отдельно, прежде чем переключиться. В то же время набирает обороты планирование в пользовательском пространстве с помощью шаблонов eBPF, что позволяет получить дополнительный контроль в зависимости от рабочей нагрузки. CFS остается актуальным для хостинговых инфраструктур, но EEVDF быстро утвердится.

По-прежнему важен четкий путь миграции: тестирование, развертывание на избранных узлах, затем расширение. Только так можно держать под контролем процентили и количество ошибок. Я держу контрольные показатели близкими к реальности, включая фазы серийной работы и медленные бэкэнды. Только после этого я вмешиваюсь в живые среды. Таким образом, прогресс достигается без неприятных сюрпризов.

Краткое резюме

Linux Scheduler CFS обеспечивает справедливое распределение, надежную интеграцию и хорошую Управление через Cgroups. С помощью подходящих параметров sysctl, чистого сродства и реалистичных квот я поддерживаю низкие задержки и высокую пропускную способность. ULE, BFS или EEVDF предлагают дополнительные рычаги для особых паттернов. Я измеряю, сравниваю и поэтапно внедряю изменения, чтобы ограничить риски. Таким образом, хостинг становится предсказуемым, а производительность - на высоте.

Текущие статьи

Планировщик ядра сервера CFS в хостинге с распределением процессорного времени
Серверы и виртуальные машины

Планировщик CFS в Linux: функциональность и альтернативы в хостинге серверов

Linux Scheduler CFS: как он работает, сервер планирования процессора и альтернативы, такие как EEVDF. Настройка ядра для оптимальной производительности хостинга.

Инструменты для нагрузочного тестирования производительности хостинга
Серверы и виртуальные машины

Нагрузочное тестирование в веб-хостинге: инструменты и значение

**Нагрузочное тестирование в веб-хостинге**: Лучшие инструменты, такие как JMeter и LoadView, для стресс-тестов и анализа производительности. Как оптимизировать свой сервер!