подача большого файла с использованием select, epoll или kqueue - PullRequest
2 голосов
/ 29 марта 2010

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

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

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

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

Ответы [ 4 ]

5 голосов
/ 02 июня 2010

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

4 голосов
/ 13 апреля 2010

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

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

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

2 голосов
/ 30 марта 2010

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

0 голосов
/ 03 сентября 2011

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

...