Почему мой скрипт сервера Perl TCP зависает со многими TCP-соединениями? - PullRequest
7 голосов
/ 19 апреля 2010

У меня странная проблема с сервером, принимающим 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, когда проблема начинает проявляться), но это может быть красная сельдь.

Что здесь может происходить?


После еще одного анализа: выяснилось, что клиент ошибся, неправильно закрыв предыдущие соединения перед попыткой следующего. На серверах в начале списка балансировки нагрузки остались устаревшие соединения.

Ответы [ 2 ]

1 голос
/ 07 июня 2010

Возможно, это не решение вашей проблемы, но может решить проблему, с которой вы столкнетесь в будущем: не забудьте закрыть () сокеты, когда вы закончите! shutdown () отключит поток, но все равно будет использовать дескриптор файла.

Так как вы сказали, что strace показывает процессы, застрявшие в read (), ваша проблема в том, что клиент не отправляет данные, которые вы ожидаете, что они будут отправлены. Вам следует либо исправить свой клиент, либо добавить сигнализацию () к процессам вашего сервера, чтобы они могли пережить мертвые клиенты.

0 голосов
/ 20 апреля 2010

Пульсирует ли он, а затем останавливается долго (около двух минут или около того), а затем снова всплывает? Если это так, возможно, у вас не установлен максимально допустимый предел открытых файлов в вашей системе.

...