Вопрос проверяет понимание стратегий выноса длительных CPU-bound задач из основного потока приложения для сохранения отзывчивости сервиса.
CPU-bound задача интенсивно использует процессор и выполняется несколько минут. Если запустить её в основном потоке веб-сервера, сервер перестанет отвечать на другие запросы до завершения задачи. Это неприемлемо для production-систем.
Самый распространённый подход — вынести задачу в фоновый процесс (воркер) и общаться с ним через очередь сообщений. Основной сервис (продюсер) отправляет задачу в очередь и сразу возвращает клиенту HTTP 202 Accepted. Воркер (консьюмер) забирает задачу, выполняет её и сохраняет результат в базу данных или отправляет уведомление.
Пример на Node.js с использованием Worker Threads:
// main.js (основной сервер)
const { Worker } = require('worker_threads');
app.post('/heavy-task', (req, res) => {
const worker = new Worker('./worker.js');
worker.postMessage(req.body.data);
worker.on('message', (result) => {
// сохраняем результат в БД
});
res.status(202).send({ status: 'accepted' });
});
// worker.js (воркер)
const { parentPort } = require('worker_threads');
parentPort.on('message', (data) => {
const result = performHeavyCpuTask(data); // долгая CPU-bound работа
parentPort.postMessage(result);
});Пример на Python с Celery и RabbitMQ:
# tasks.py
from celery import Celery
app = Celery('tasks', broker='pyamqp://guest@localhost//')
@app.task
def heavy_cpu_task(data):
# CPU-bound логика
return result
# main.py (Flask)
from tasks import heavy_cpu_task
@app.route('/heavy-task', methods=['POST'])
def start_task():
task = heavy_cpu_task.delay(request.json)
return {'task_id': task.id}, 202Вынос CPU-bound задач в фоновые воркеры через очередь сообщений — стандартный паттерн для масштабируемых систем. Он сохраняет отзывчивость основного сервиса, позволяет легко масштабировать обработку и обеспечивает надёжность (задачи не теряются при падении воркера).