shad-go/distbuild/pkg/scheduler/README.md

56 lines
5.3 KiB
Markdown
Raw Normal View History

2020-04-05 11:29:46 +00:00
# scheduler
Пакет `scheduler` реализует планировщик системы. `scheduler.Scheduler` хранит полное состояние кластера
и принимает решение на каком воркере и какой джоб нужно запустить.
Шедулер является точкой координации между воркерами и билдами. Бегущие билды обращаются к шедулеру,
передавая джобы в функцию `ScheduleJob`. Воркеры забирают джобы из шедулера вызывая функцию `PickJob`.
2020-04-21 22:15:29 +00:00
После того, как воркер завершил выполнение джоба, он вызывает функцию `OnJobComplete`. Эту функцию
могут вызвать даже для того джоба, который никто не шедулил. В этом случае планировщик просто должен
запомнить, что результаты джоба сохранены в кеше на воркере.
2020-04-21 22:17:51 +00:00
Фукнция `LocateArtifact` должна возвращать имя любого воркера, который хранит в кеше заданный артефакт.
Эта функция не нужна в этой задаче, но он потребуется вам для реализации передачи артефактов между
воркерами.
2021-04-25 13:10:08 +00:00
Для того, чтобы зачесть домашнее задание, достаточно реализовать упрошённый алгоритм планирования с
одной глобальной очередью. Функция `ScheduleJob` должна помещать `job` в очередь, или возвращать ссылку на существующий
`pendingJob`. Функция `PickJob` должна извлекать первый элемент из очереди. Обратите внимание, что функция `PickJob`
принимает контекст. Поскольку это блокирующая операция, она должна поддерживать отмены. Если вы забудете
2021-04-25 18:16:24 +00:00
реализовать отмену в этом месте, интеграционные тесты будут зависать.
2020-04-05 11:29:46 +00:00
## Алгоритм планирования
2021-04-25 13:10:08 +00:00
*Далее описывается продвинутый алгоритм планирования. Алгоритм проверяется в отдельной задаче `smartsched`.
Для зачёта по домашнему заданию, реализовывать этот алгоритм не обязательно.*
2020-04-05 11:29:46 +00:00
Планировщик поддерживает множество очередей:
2021-04-25 13:10:08 +00:00
1. Одна глобальная очередь.
2020-04-05 11:29:46 +00:00
2. По две локальные очереди на воркер.
При запросе нового джоба воркер выбирает случайную джобу из трех очередей - глобальной, и двух локальных относящихся
к этому воркеру. Случайная очередь выбирается одним вызовом `select {}`.
Ожидающий исполнения джоб всегда находится в первой локальной очереди воркеров, на которых есть
результаты работы этого джоба.
2020-04-05 15:19:59 +00:00
Если джоб ждёт выполнения дольше `CacheTimeout` или если в момент `SchedulerJob` джоба не было в кеше ни на одном
из воркеров, то он попадает во все вторые локальные очереди воркеров, на которых есть хотя бы один артефакт
2020-04-05 11:29:46 +00:00
из множества зависимостей этого джоба.
Определения первой и второй локальной очереди не зависят от того, в каком порядке в шедулер пришли джобы
2020-04-05 15:19:59 +00:00
и информация о кеше артефактов. То есть, если джоб уже находится в глобальной очереди, и в этот момент приходит
информация, что этот джоб находится в кеше на воркере `W0`, то джоб должен быть добавлен
2020-04-05 11:29:46 +00:00
в первую локальную очередь `W0`.
Если джоб ждёт выполнения дольше `DepTimeout`, то он помещается в глобальную очередь.
## Тестирование
Вместо реального времени, юниттесты шедулера используют библиотеку `clockwork`. Это накладывает ограничения
на детали вашей реализации. Ожидание `CacheTimeout` и `DepTimeout` должно быть реализовано как `select {}` на
2021-04-25 13:10:08 +00:00
канале, который вернула функция `TimeAfter`. Мы считаем что `CacheTimeout < DepTimeout`, и ожидание этих
таймаутов происходит последовательно в одной горутине.