Асинхронный сервер держит 1000 клиентов, но задержки выросли до секунд
Сервер на C++ обслуживает более 1000 одновременных соединений: один поток, цикл событий на epoll, все операции с сокетами асинхронные. В обработчике одного из типов запросов выполняется синхронный запрос в PostgreSQL и чтение файла с диска — это примерно 3% всех запросов.
Под нагрузкой задержки растут у всех клиентов, включая тех, кто шлёт простейшие запросы. Загрузка CPU при этом невысокая.
В чём причина?
- Синхронный вызов в обработчике блокирует весь цикл событий: пока он идёт, другие соединения не обслуживаются
- Мал размер очереди ожидающих соединений: нужно увеличить backlog в вызове listen, тогда задержки уйдут
- epoll перестаёт масштабироваться после нескольких сотен дескрипторов, нужно переходить на периодический опрос
- Включён алгоритм Нейгла: он придерживает мелкие ответы, из-за чего задержки растут сразу на всех соединениях
