У меня странная проблема с сервером, принимающим TCP-соединения. Хотя обычно некоторые процессы ожидают, при некотором объеме соединений он зависает.
Длинная версия:
Сервер написан на Perl и связывает сокет $srv
с флагом повторного использования и слушает == 5. После этого он разветвляется на 10 процессов с циклом $clt=$srv->accept(); do_processing($clt); $clt->shutdown(2);
Клиент, написанный на C, также очень прост - он отправляет несколько строк, затем получает все доступные строки и выполняет shutdown(sockfd, 2);
Асинхронизация не происходит, и в конце очереди и для отправки, и для приема пусты (как сообщает netstat
).
Соединения длятся всего ~ 20мс. Все клиенты ведут себя одинаково, имеют одинаковую реализацию и т. Д. Теперь, допустим, я принимаю X
подключения от клиента 1 и еще один X
от клиента 2. Процессы по-прежнему сообщают, что они все время простаивают. Если я добавлю еще X
соединений от клиента 3, внезапно серверные процессы начнут зависать сразу после принятия. Первая блокирующая вещь, которую они делают после accept();
, это while (<$clt>) ...
- но они не получают никаких данных (уже с первой попытки). Внезапно все 10 процессов находятся в этом состоянии и не перестают ждать. На strace
процессы сервера, кажется, зависают на read()
, что имеет смысл.
В состоянии TIME_WAIT
имеется множество соединений, принадлежащих этому серверу (~ 100, когда проблема начинает проявляться), но это может быть красная сельдь.
Что здесь может происходить?
После еще одного анализа: выяснилось, что клиент ошибся, неправильно закрыв предыдущие соединения перед попыткой следующего. На серверах в начале списка балансировки нагрузки остались устаревшие соединения.