В настоящее время существует два основных принципа для параллельного доступа к веб-серверу с различными преимуществами и недостатками:
- Блокировка
- Не-Блокировка
Блокировка веб-серверов
Первая концепция блокировка, многопоточный сервер имеет конечное количество потоков в пуле,Каждый запрос будет назначен определенному потоку, и этот поток будет назначаться, пока запрос не будет полностью обработан.Это в основном то же самое, что и то, как работает очередь покупок в супермаркете, клиент одновременно с возможными параллельными линиями.В большинстве случаев запрос на веб-сервере будет простаивать большую часть времени при обработке запроса.Это связано с тем, что он должен ждать ввода / вывода: прочитать сокет, записать в БД (который также является в основном IO), прочитать результат и записать в сокет.Кроме того, использование / создание группы потоков является медленным (переключение контекста) и требует много памяти.Поэтому эта концепция часто не использует аппаратные ресурсы, которые она имеет очень эффективно, и имеет жесткое ограничение на количество клиентов, которые могут обслуживаться параллельно.Это свойство неправильно используется в так называемых «голодных» атаках, например, slow loris , атака, при которой обычно один клиент может без труда приложить усилия к большому многопоточному веб-серверу.
Резюме
- (+) более простой код
- (-) жесткое ограничение параллельных клиентов
- (-) требует больше памяти
- (-) неэффективное использованиеаппаратного обеспечения для обычной работы веб-сервера
- (-), удобного для DOS
Большинство «обычных» веб-серверов работают таким образом, например, старый tomcat, Apache Webserver и все Servlet
старше 3 или 3,1 и т. д.
Неблокирующие веб-серверы
Напротив, неблокирующий веб-сервер может обслуживать несколько клиентов только с одним потоком.Это связано с тем, что он использует неблокирующие функции ввода-вывода ядра .Это просто вызовы ядра, которые немедленно возвращаются и перезваниваются, когда что-то можно записать или прочитать, что делает процессор свободным вместо выполнения другой работы.Повторно используя нашу метафору супермаркета, это будет похоже на то, что когда кассиру нужен супервайзер для решения проблемы, он не ждет и не блокирует весь переулок, а начинает проверять следующего клиента до тех пор, пока супервайзер не приедет и не решит проблему первогоcustomer.
Это часто делается в цикле событий или более высоких абстракциях как green-threads или волокон .По сути, такие серверы не могут обрабатывать что-либо одновременно (конечно, вы можете иметь несколько неблокирующих потоков), но они могут обслуживать тысячи клиентов параллельно, потому что потребление памяти не будет столь сильно масштабироватьсякак и в случае многопоточной концепции (читай: нет ограничений по максимальному количеству параллельных клиентов).Также отсутствует переключение контекста потока.Недостатком является то, что неблокирующий код часто более сложен для чтения и записи (например, callback-hell ) и не очень хорошо справляется с ситуацией, когда запрос выполняет много дорогостоящей работы процессора.
Сводка
- (-) более сложный код
- (-) производительность хуже при выполнении задач с интенсивным использованием процессора
- (+) использует ресурсы гораздо чащеэффективно в качестве веб-сервера
- (+) гораздо больше параллельных клиентов без жесткого ограничения (кроме максимального объема памяти)
Большинство современных «быстрых» веб-серверов и инфраструктура обеспечивают неблокированиепонятия: Netty, Vert.x, Webflux, nginx, сервлет 3.1+, Node, Go Webservers.
В качестве дополнительного примечания, глядя на эту страницу тестов, вы увидите, что большинство самых быстрых веб-серверов обычноНеблокирующие: https://www.techempower.com/benchmarks/
См. также