Является ли «epoll» основной причиной того, что Tornadoweb (или Nginx) так быстр? - PullRequest
23 голосов
/ 06 апреля 2010

Tornadoweb и Nginx на данный момент являются популярными веб-серверами, и многие сравнительные тесты показывают, что они имеют лучшую производительность, чем Apache при определенных обстоятельствах. Итак, мой вопрос:

Является ли «эполл» самой важной причиной, по которой они так быстры? И что я могу извлечь из этого, если я хочу написать хороший сервер сокетов?

Ответы [ 2 ]

65 голосов
/ 24 мая 2010

Если вы хотите написать сокет-сервер, хорошей отправной точкой является статья Дэна Кегеля C10k, опубликованная несколько лет назад:

http://www.kegel.com/c10k.html

Мне также очень понравилось Руководство Биджа по сетевому программированию:

http://beej.us/guide/bgnet/

Наконец, если вам нужен хороший справочник, есть сетевое программирование UNIX от W. Richard Stevens et. al.:

http://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/ref=dp_ob_title_bk

В любом случае, чтобы ответить на ваш вопрос, основное различие между Apache и Nginx состоит в том, что Apache использует один поток на клиент с блокирующим вводом / выводом, тогда как Nginx является однопоточным с неблокирующим вводом / выводом. Рабочий пул Apache действительно снижает накладные расходы при запуске и удалении процессов, но он все же заставляет ЦП переключаться между несколькими потоками при обслуживании нескольких клиентов. Nginx, с другой стороны, обрабатывает все запросы в одном потоке. Когда один запрос должен сделать сетевой запрос (скажем, к бэкэнду), Nginx присоединяет обратный вызов к бэкэнд-запросу и затем работает с другим активным клиентским запросом. На практике это означает, что он возвращается в цикл обработки событий (epoll, kqueue или select) и запрашивает дескрипторы файлов, которым есть что сообщить. Обратите внимание, что системный вызов в цикле основного события на самом деле является блокирующей операцией, поскольку ничего не нужно делать, пока один из файловых дескрипторов не будет готов для чтения или записи.

Так что это главная причина, по которой Nginx и Tornado эффективны в обслуживании множества одновременных клиентов: существует только один процесс (таким образом, экономит ОЗУ) и только один поток (таким образом, экономит ЦП от переключений контекста). Что касается epoll, то это просто более эффективная версия select. Если имеется N открытых дескрипторов файлов (сокетов), это позволяет вам выбрать те, которые готовы к чтению в O (1) вместо O (N) времени. Фактически, Nginx может использовать select вместо epoll, если вы скомпилируете его с опцией --with-select_module, и я уверен, что он все равно будет более эффективным, чем Apache. Я не так хорошо знаком с внутренними компонентами Apache, но быстрый grep показывает, что он использует select и epoll - возможно, когда сервер прослушивает несколько портов / интерфейсов, или если он выполняет одновременные запросы бэкэнда для одного клиента.

Между прочим, я начал с того, что пытался написать базовый сервер сокетов и хотел выяснить, насколько Nginx так чертовски эффективен. Изучив исходный код Nginx и прочитав те руководства / книги, на которые я ссылался выше, я обнаружил, что будет проще писать модули Nginx вместо моего собственного сервера. Так родился полулегендарный справочник Эмиллера по разработке модулей Nginx:

http://www.evanmiller.org/nginx-modules-guide.html

(Предупреждение: Руководство написано для Nginx 0.5-0.6, и API-интерфейсы могли измениться.) Если вы что-то делаете с HTTP, я бы сказал, чтобы Nginx попробовал, потому что он проработал все волосатые детали работы с тупые клиенты. Например, небольшой сервер сокетов, который я написал для удовольствия, прекрасно работал со всеми клиентами - кроме Safari, и я так и не понял, почему. Даже для других протоколов Nginx может быть правильным путем; события довольно хорошо абстрагированы от протоколов, поэтому они могут прокси HTTP и IMAP. Кодовая база Nginx чрезвычайно хорошо организована и очень хорошо написана, за одним исключением, которое стоит упомянуть. Я бы не стал следовать его примеру, когда дело доходит до ручного парсера протоколов; вместо этого используйте генератор парсера. Я написал кое-что об использовании генератора синтаксических анализаторов (Ragel) с Nginx здесь:

http://www.evanmiller.org/nginx-modules-guide-advanced.html#parsing

Все это, вероятно, было больше информации, чем вы хотели, но, надеюсь, вы найдете некоторые из них полезными.

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

Да и нет. Хотя они оба используют epoll, технически они оба используют цикл обработки событий для обработки запросов. Вы можете найти больше информации о том, что такое циклы событий и как они используются в wikipedia .

Проверьте libevent (используется gevent , обычно быстрее и стабильнее, чем торнадо) или libev для реализаций.

...