Все главы учебника
Содержание учебника
Глава 03 / Бесплатный backend-путь

Фоновые задания: очередь, обработчики и остановка

40 мин чтенияКонтент v0.8.0

Почему нужен предел

Если создавать горутину на каждый запрос, число работ растёт вместе с потоком клиентов. Каждая работа занимает память и ресурсы. Вместо этого создайте фиксированное число обработчиков Workers и очередь вместимостью QueueSize. Обработчик берёт задание, переводит его в running, вызывает Process, а затем сохраняет done или failed.

Здесь Process(ctx, text) возвращает Result или ошибку. В обычном режиме она вызывает вашу Analyze. В тестах её заменяют управляемой функцией: это позволяет удержать обработчики занятыми и проверить очередь без случайных задержек. Ограничение очереди относится к ожиданию, а число обработчиков — к одновременному выполнению. Это разные пределы.

Что прочитать

Пройдите горутины, модель памяти, каналы, select, примитивы синхронизации, context, паттерны и утечки и гонки. Выполните упражнения глав; начните с тренажёрных задач на канал, ожидание и пул, указанных в этих главах. atomic и подробности планировщика пока можно читать после проекта.

Разберите рост нагрузки: очередь не увеличивает скорость обработки, а позволяет ограниченное время пережить всплеск. Чтение этих глав входит в этап; минипример из проекта не заменяет весь разбор конкурентности.

Реализуйте ограниченную обработку

Запускайте пул один раз при создании приложения. Не держите mutex во время вызова Process: иначе долгий расчёт блокирует чтение статуса и остальных обработчиков. Общая map заданий и изменения состояний должны быть защищены. Возвращая запись клиенту, не оставляйте ему доступ к изменяемому общему объекту.

Если приём в очередь невозможен сразу из-за заполнения, верните 429. Отклонённый запрос не должен оставлять «вечное» задание в хранилище. После начала остановки новый POST получает 503; чтение существующих записей остаётся отдельным действием. Решите, под какой синхронизацией проверяются приём и остановка, чтобы два конкурентных запроса не нарушили договор.

Shutdown(ctx) прекращает приём и ждёт уже принятые задания. Если время ожидания истекло, приложение сообщает отмену текущим обработчикам. Отмена кооперативна: Process должна проверять ctx.Done() и возвращаться. Произвольный бесконечный цикл без проверок context нельзя остановить этим сигналом. Завершение Shutdown и отмена — разные события; ошибка ожидания не доказывает, что весь пользовательский код уже завершился.

Проверьте поведение

go test ./... -run '^TestStage0[123]' -count=1
go test -race ./... -run '^TestStage0[123]' -count=1

Race detector запускают локально. Для него нужен поддерживаемый Go инструментами компьютер; на некоторых системах также потребуется C-компилятор. Если команда недоступна, сохраните сообщение и проверьте среду, а не называйте обычный тест проверкой гонок. Успешный -race касается только выполненных сценариев.

Самостоятельно удержите два обработчика на тестовом канале, заполните очередь и проверьте отклонение следующего запроса. Освободите обработку и дождитесь результата без time.Sleep как доказательства. Отдельно вызовите остановку с коротким дедлайном и убедитесь, что тестовая Process увидела отмену.

Ошибки: закрыть канал, пока другой поток ещё отправляет; добавлять счётчик WaitGroup после запуска горутины; ждать свободного места бесконечно в HTTP-запросе; считать context принудительным завершением; прятать гонку увеличением задержки теста.

Когда идти дальше

Нарисуйте владельца очереди и точки остановки. Объясните, что произойдёт с занятым обработчиком, полным буфером и новым запросом в один момент. Если можете показать предел работы и завершение пула тестом, переходите к сохранению заданий.

Самопроверка этапа

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

Что выполнено

Для завершения отметьте все критерии и добавьте объяснение.