Ответ 1
1. Зависит от веб-сервера (а иногда и от конфигурации). Описание различных моделей:
-
Apache с mpm_prefork (по умолчанию в unix): обрабатывается за запрос. Чтобы свести к минимуму время запуска, Apache поддерживает пул простаивающих процессов, ожидающих обработки новых запросов (которые вы настраиваете размер). Когда приходит новый запрос, мастер-процесс делегирует его доступному рабочему, в противном случае создается новый. Если бы поступило 100 запросов, если у вас не было 100 рабочих, работающих на холостом ходу, для обработки нагрузки необходимо выполнить некоторую разметку. Если количество незанятых процессов превышает значение MaxSpare, некоторые из них будут получены после завершения запросов до тех пор, пока не будет достаточно всего количества незанятых процессов.
-
Apache с mpm_event, mpm_worker, mpm_winnt: поток за запрос. Аналогично, в большинстве ситуаций apache поддерживает пул простаивающих потоков, а также настраивается. (Небольшая деталь, но функционально такая же: mpm_worker запускает несколько процессов, каждый из которых многопоточен).
-
Nginx/Lighttpd: это легкие серверы на основе событий, которые используют select()/epoll()/poll() для мультиплексирования нескольких сокетов без необходимости нескольких потоков или процессов. Благодаря очень тщательной кодировке и использованию неблокирующих API, они могут масштабироваться до тысяч одновременных запросов на товарное оборудование, предоставляя доступную полосу пропускания и правильно настроенные ограничения файлового дескриптора. Суть в том, что реализация традиционных встроенных языков сценариев практически невозможна в контексте сервера, это отрицательно повлияет на большинство преимуществ. Оба поддерживают FastCGI, однако, для внешних языков сценариев.
2. В зависимости от языка или на некоторых языках, на какой модели развертывания вы используете. Некоторые конфигурации серверов допускают только определенные модели развертывания.
-
Apache mod_php, mod_perl, mod_python: эти модули запускают отдельный интерпретатор для каждого работника apache. Большинство из них не могут работать с mpm_worker очень хорошо (из-за различных проблем с обеспечением безопасности потоков в клиентском коде), поэтому они в основном ограничены forking-моделями. Это означает, что для каждого процесса apache у вас есть интерпретатор php/perl/python. Это значительно увеличивает объем памяти: если данный apache-работник обычно занимает около 4 МБ памяти в вашей системе, один с PHP может принимать 15 МБ, а один с Python может принимать 20-40 МБ для среднего приложения. Некоторые из них будут разделяемой памятью между процессами, но в целом эти модели очень трудно масштабировать очень большие.
-
Apache (поддерживаемые конфигурации), Lighttpd, CGI: это, в основном, метод отмирания хостинга. Проблема с CGI заключается в том, что вы не только разворачиваете новый процесс обработки запросов, вы делаете это для -все-запроса, а не только тогда, когда вам нужно увеличить нагрузку. Поскольку динамические языки сегодня имеют довольно большое время запуска, это создает не только много работы для вашего веб-сервера, но и значительно увеличивает время загрузки страницы. Небольшой perl script может работать нормально как CGI, но большое приложение python, ruby или java довольно громоздко. В случае Java вы можете ожидать второй или более только для запуска приложения, только чтобы повторить это снова при следующем запросе.
-
Все веб-серверы, FastCGI/SCGI/AJP: это "внешняя" модель хостинга динамических языков. Существует целый список интересных вариантов, но суть в том, что ваше приложение прослушивает какой-то сокет, а веб-сервер обрабатывает HTTP-запрос, а затем отправляет его через другой протокол в сокет только для динамических страниц (статические страницы обычно обрабатываются непосредственно веб-сервером).
Это дает много преимуществ, потому что вам понадобятся менее динамичные рабочие, чем вам нужна возможность обработки соединений. Если для каждых 100 запросов половина предназначена для статических файлов, таких как изображения, CSS и т.д., И, кроме того, если большинство динамических запросов коротки, вы можете получить 20 динамических работников, которые будут обрабатывать 100 одновременных клиентов. То есть, поскольку обычное использование поддерживаемого соединения с сервером на 80% бездействует, ваши динамические интерпретаторы могут обрабатывать запросы от других клиентов. Это намного лучше, чем подход mod_php/python/perl, где, когда пользователь загружает файл CSS или вообще ничего не загружает, ваш интерпретатор сидит там с использованием памяти и не выполняет никаких действий.
-
Apache mod_wsgi: Это относится, в частности, к хостингу python, но он использует некоторые преимущества приложений, размещенных на веб-сервере (простая настройка) и внешнего хостинга (мультиплексирование процессов). Когда вы запускаете его в режиме демона, mod_wsgi только делегирует запросы вашим рабочим демонам, когда это необходимо, и, таким образом, 4 демона могут обрабатывать 100 одновременных пользователей (зависит от вашего сайта и его рабочей нагрузки).
-
Phusion Passenger: Пассажир - это система хостинга apache, которая в основном предназначена для размещения рубиновых приложений, и, как и mod_wsgi, обеспечивает преимущества как внешнего, так и управляемого веб-сервера.
3. Опять же, я разберу вопрос на основе моделей хостинга, где это применимо.
-
mod_php, mod_python, mod_perl: Только общие библиотеки C вашего приложения обычно будут совместно использоваться между работниками Apache. Это происходит из-за того, что apache сначала запускает, а затем загружает динамический код (который из-за тонкостей в основном не может использовать общие страницы). Переводчики не общаются друг с другом в рамках этой модели. Глобальные переменные обычно не разделяются. В случае mod_python вы можете иметь глобальные переменные между запросами в процессе, но не через процессы. Это может привести к некоторому очень странному поведению (браузеры редко поддерживают одно и то же соединение навсегда, а большинство открывают несколько для данного веб-сайта), поэтому будьте очень осторожны с тем, как вы используете глобальные переменные. Используйте что-то вроде memcached или базы данных или файлов для таких вещей, как хранение сеанса и другие кэш-биты, которые необходимо использовать.
-
FastCGI/SCGI/AJP/Proxied HTTP: поскольку ваше приложение по сути является сервером само по себе, это зависит от языка, на котором написан сервер (обычно это тот же язык, что и ваш код, но не всегда) и различные факторы. Например, в большинстве развертываний Java используется поток за запрос. Python и его "flup" FastCGI-библиотека могут работать как в предпродажном, так и в потоковом режиме, но поскольку Python и его GIL ограничены, вы, скорее всего, получите лучшую производительность от prefork.
-
mod_wsgi/пассажир: mod_wsgi в режиме сервера можно настроить, как он обрабатывает вещи, но я бы порекомендовал вам дать ему фиксированное количество процессов. Вы хотите сохранить свой код python в памяти, развернуться и подготовиться к работе. Это лучший подход для обеспечения предсказуемости и низкого уровня ожидания.
Почти во всех упомянутых выше моделях время жизни процесса/потока больше, чем один запрос. Большинство настроек следуют некоторым вариантам в модели apache: Храните некоторых запасных рабочих вокруг, при необходимости создавайте больше, когда их можно использовать, когда их слишком много, на основе нескольких настраиваемых ограничений. Большинство из этих настроек - не уничтожить процесс после запроса, хотя некоторые могут очистить код приложения (например, в случае PHP fastcgi).
4. Если вы скажете, что "веб-сервер может обрабатывать только 100 запросов", это зависит от того, означает ли вы собственно веб-сервер или динамическую часть веб-сервера. Существует также разница между фактическими и функциональными пределами.
В случае Apache, например, вы настроите максимальное количество рабочих (соединений). Если это число соединений было 100 и было достигнуто, никакие соединения не будут приняты apache до тех пор, пока кто-то не отключится. С включенным режимом keep-alive эти 100 соединений могут оставаться открытыми в течение длительного времени, намного дольше, чем один запрос, а остальные 900 человек, ожидающих запросы, вероятно, будут отсутствовать.
Если у вас есть достаточно высокие лимиты, вы можете принять всех этих пользователей. Однако даже с самым легким апачем стоимость составляет около 2-3 МБ на одного работника, поэтому только с помощью apache вы можете говорить о 3gb + памяти только для обработки соединений, не говоря уже о других возможно ограниченных ресурсах ОС, таких как идентификаторы процессов, дескрипторы файлов, и буферов, и это до рассмотрения вашего кода приложения.
Для lighttpd/Nginx они могут обрабатывать большое количество подключений (тысяч) в крошечном объеме памяти, часто всего несколько мегабайт на тысячу подключений (зависит от таких факторов, как буферы и то, как настроен async IO apis). Если мы исходим из предположения, что большинство ваших подключений остаются в живых и 80% (или более) бездействуют, это очень хорошо, поскольку вы не тратите время на динамическое время или большую часть памяти.
В любой внешней размещенной модели (mod_wsgi/fastcgi/ajp/proxied http), скажем, у вас только 10 работников и 1000 пользователей делают запрос, ваш веб-сервер будет помещать запросы вашим динамическим сотрудникам. Это идеально: если ваши запросы возвращаются быстро, вы можете продолжать работать с гораздо большей нагрузкой на пользователя, не требуя больше рабочих. Обычно премия - это соединения памяти или БД, и в порядке очередности вы можете обслуживать гораздо больше пользователей с одинаковыми ресурсами, вместо того чтобы отрицать некоторых пользователей.
Будьте осторожны: скажите, что у вас есть одна страница, которая строит отчет или выполняет поиск, и занимает несколько секунд, и многие пользователи связывают рабочих с этим: кто-то, желающий загрузить вашу первую страницу, может быть поставлен в очередь на несколько секунд в то время как все эти длительные запросы завершаются. Альтернативы используют отдельный пул работников для обработки URL-адресов в вашем разделе приложения для отчетов или для отдельной публикации (например, в фоновом задании), а затем для последующего опроса своего завершения. Здесь много вариантов, но вам нужно подумать над своим приложением.
5.. Большинство людей, использующих apache, которым необходимо обрабатывать множество одновременных пользователей, по причине большого объема памяти, отключились. Или Apache с включенной поддержкой, с коротким сроком хранения в режиме ожидания, скажем, 10 секунд (так что вы можете получить свою первую страницу и изображения /CSS в одной загрузке страницы). Если вам действительно нужно масштабировать до 1000 подключений или больше, и вы хотите продолжать жить, вы захотите посмотреть Nginx/lighttpd и другие облегченные серверы на основе событий.
Можно отметить, что если вы хотите использовать apache (для удобства использования конфигурации или для размещения определенных настроек), вы можете поместить Nginx перед apache, используя HTTP-прокси. Это позволит Nginx обрабатывать связи keep-alive (и, желательно, статические файлы) и apache для обработки только работы grunt. Интересно, что Nginx лучше, чем apache, при написании лог файлов. Для развертывания производства мы были очень довольны nginx перед apache (с mod_wsgi в этом случае). Apache не выполняет регистрацию доступа и не обрабатывает статические файлы, что позволяет нам отключить большое количество модулей внутри apache, чтобы сохранить его небольшую площадь.
Я уже ответил на это уже, но нет, если у вас длинное соединение, он не должен иметь никакого отношения к тому, как долго работает интерпретатор (пока вы используете внешнее размещенное приложение, которое к настоящему времени должно быть ясными значительно превосходит). Поэтому, если вы хотите использовать комету и долго оставаться в живых (что обычно хорошо, если вы можете справиться с этим), рассмотрите nginx.
Бонусный вопрос FastCGI. Вы упомянули, что fastcgi может мультиплексироваться в одном соединении. Это действительно поддерживается протоколом (я считаю, что концепция известна как "каналы" ), так что теоретически один сокет может обрабатывать множество соединений. Тем не менее, это не обязательная особенность разработчиков fastcgi, и на самом деле я не верю, что есть один сервер, который использует это. Большинство респондентов fastcgi не используют эту функцию, потому что реализация этого очень сложна. Большинство веб-серверов будут производить только один запрос через данный сокет fastcgi за раз, а затем сделать следующий через этот сокет. Таким образом, у вас часто есть только один сокет fastcgi для процесса/потока.
Используется ли ваше приложение fastcgi для обработки или потоковой передачи (и реализуете ли вы его через "главный" процесс, принимающий соединения, делегирование или просто много процессов, каждый из которых делает свое дело) зависит от вас; и зависит от возможностей вашего языка программирования и ОС. В большинстве случаев все, что по умолчанию используется библиотекой, должно быть прекрасным, но будьте готовы к некоторому бенчмаркингу и настройке параметров.
Что касается общего состояния, я рекомендую вам притвориться, что каких-либо традиционных применений совместного процесса в процессе работы не существует: даже если они могут работать сейчас, возможно, вам придется разделить своих динамических работников на нескольких компьютерах позже. Для таких штатов, как тележки для покупок и т.д.; db может быть лучшим вариантом, информация для входа в сеанс может храниться в защищенных файлах, а для временного состояния что-то похожее на memcached довольно аккуратно. Чем меньше вы полагаетесь на функции, которые обмениваются данными (подход "общий-ничего" ), тем больше вы можете масштабировать в будущем.
Postscript: Я написал и развернул множество динамических приложений во всей области настроек выше: все перечисленные выше веб-серверы и все в диапазоне PHP/Python/Ruby/Java. Я интенсивно тестировал (используя как бенчмаркинг, так и наблюдение в реальном мире) методы, и результаты иногда удивляют: меньше часто бывает больше. После того как вы ушли от размещения своего кода в процессе веб-сервера, вы часто можете уйти с очень небольшим количеством сотрудников FastCGI/Mongrel/mod_wsgi/etc. Это зависит от того, сколько времени ваше приложение остается в БД, но очень часто бывает, что больше процессов, чем 2 * количество процессоров, на самом деле ничего не принесет вам.