Backpressure и ограничение нагрузки в Go-сервисе
Вопрос
Сервис принимает события по HTTP и пишет их в базу. При всплеске трафика база не успевает. Как вы организуете конкурентность и backpressure?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Ограниченная очередь (буферизованный канал) между приёмом и записью
Фиксированный пул писателей под возможности базы, батчинг
При заполненной очереди не блокировать вечно: select с default или таймаутом, ответ 429/503
Rate limit и лимит одновременных запросов на входе
Graceful shutdown с дочиткой очереди и метрики длины очереди
Надёжность: если терять нельзя, внешняя очередь (Kafka) вместо памяти
Что могут спросить следом
- Что будет с событиями в памяти при падении процесса?
- Как выбрать размер батча и буфера?
Разбор
Разделяю приём и запись. Обработчик кладёт событие в буферизованный канал фиксированного размера, а пул из N писателей читает его и пишет в базу батчами: копит до 500 событий или 100 мс по тикеру, потом один INSERT. N подбираю под пул соединений базы. Ключевое: обработчик не блокируется бесконечно. Отправка в select с default или коротким таймаутом, и если очередь полна, отвечаю 429 или 503 с Retry-After. Это и есть backpressure: клиент узнаёт, что надо притормозить, а сервис не раздувает память. Плюс rate limit на входе по клиенту. Метрики: длина очереди, время в очереди, ошибки записи. При shutdown перестаю принимать, закрываю канал, писатели дописывают остаток. Если события терять нельзя, очередь в памяти не подходит: при падении процесса буфер пропадёт, поэтому пишу в Kafka или в таблицу-журнал, а в базу переливаю отдельным консюмером.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.