Как распараллелить обработку в Python-сервисе
Вопрос
Нужно обработать 1 млн изображений: скачать по URL, уменьшить, загрузить в S3. Как вы это распараллелите на Python?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Разделить этапы: скачивание и загрузка I/O-bound, ресайз CPU-bound
I/O: asyncio или пул потоков с ограничением параллелизма
CPU: пул процессов по числу ядер или библиотека, отпускающая GIL
Очередь между этапами, обратное давление, батчи
Масштабирование на несколько машин через очередь задач
Ретраи, идемпотентность, учёт прогресса
Что могут спросить следом
- Как ограничить число одновременных запросов к S3?
- Что будет, если процесс упадёт на середине?
Разбор
Образцовый ответ: «Сначала разделю работу по характеру нагрузки. Скачивание и загрузка в S3 это ожидание сети, ресайз это процессор. Для сетевых этапов возьму asyncio с HTTP-клиентом и семафором на, скажем, 100 одновременных запросов, либо пул потоков, если библиотеки синхронные. Ресайз отдам в ProcessPoolExecutor по числу ядер; Pillow частично отпускает GIL, но процессы надёжнее. Этапы свяжу очередями с ограниченным размером, чтобы скачивание не убегало вперёд и не забивало память. Миллион файлов на одной машине долго, поэтому вынесу задачи в брокер, Celery или аналог, и запущу несколько воркеров на разных машинах. Каждую задачу делаю идемпотентной: ключ в S3 детерминирован, повторная обработка безопасна. Плюс ретраи на временные ошибки сети, учёт обработанных id, чтобы после падения продолжить, и метрики скорости и ошибок».
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.