обслуживание большого файла с помощью select, epoll или kqueue

Nginx использует epoll или другие методы мультиплексирования (выбор) для обработки нескольких клиентов, то есть он не создает новый поток для каждого запроса, в отличие от apache.

Я попытался воспроизвести то же самое в своей собственной тестовой программе, используя select. Я мог бы принимать соединения от нескольких клиентов, создав неблокирующий сокет и используя select, чтобы решить, какой клиент обслуживать. Моя программа просто возвращает им свои данные. Она отлично работает для передачи небольших данных (несколько байтов на клиента).

Проблема возникает, когда мне нужно отправить большой файл по соединению с клиентом. Поскольку у меня есть только один поток для обслуживания всех клиентов до тех пор, пока я не закончу чтение файла и запись его в сокет, я не могу возобновить обслуживание другого клиента.

Есть ли известное решение этой проблемы, или лучше создавать поток для каждого такого запроса?


person xask    schedule 29.03.2010    source источник


Ответы (4)


При использовании select вы не должны отправлять весь файл сразу. Если вы, например. используют sendfile для этого, он будет блокироваться до тех пор, пока весь файл не будет отправлен. Вместо этого используйте небольшой буфер и отправляйте небольшие данные каждому клиенту за раз. Затем используйте select, чтобы определить, когда сокет снова будет готов для записи, и отправьте еще немного, пока все данные не будут отправлены. Это позволит вам обрабатывать несколько клиентов параллельно.

person Chris    schedule 02.06.2010

Самый простой подход — создать поток для каждого запроса, но это, конечно, не самый масштабируемый подход. Я думаю, что в настоящее время практически все высокопроизводительные веб-серверы используют различные асинхронные подходы, основанные на таких вещах, как epoll (Linux), kqueue (BSD) или IOCP (Windows).

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

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

person Peter Hansen    schedule 13.04.2010

Для справки может быть полезно прочитать http://www.kegel.com/c10k.html.

person dangerousdave    schedule 30.03.2010

Я думаю, вы используете свой обратный вызов для обработки одного соединения. Это не так, как это было разработано. Ваш обратный вызов должен обрабатывать любую тысячу подключений, которые вы планируете обслуживать, т. е. из числа файловых дескрипторов, которые вы получаете в качестве параметра, вы должны знать (читая глобальные переменные), что делать с этим клиентом, либо читать ( ) или send() или... что угодно

person Nulik    schedule 02.09.2011