Pull to refresh

Comments 24

К сожалению, из-за форматирования, т.е. отсутствия оного, статья нечитабельная :(
Если вчитываться, то читабельная.
По теме — жаль, текущие кейсы и задачи не генерируют условий «к вам сейчас зайдёт 100000 посетителей, каждому надо отдать баннер».
Сейчас nxweb намного более функционален. Хотя, если кто-то пишет веб-приложения на ассемблере, то rwasa – самое то.
Я – разработчик nxweb. Данная статья была написана в декабре 2011 года, но почему-то только сейчас вышла из песочницы. Через три с половиной года. Попытаюсь немного освежить информацию.

За прошедшее время nxweb оброс немалым функционалом:

  • http-proxy (удобно для Java)
  • встроенный Python
  • шаблоны страниц с наследованием блоков
  • SSL
  • файловый кеш ответов бекенда
  • кешируемое gzip-сжатие
  • масштабирование изображений
  • конфиг-файл в формате json
  • подгружаемые модули
  • access log
  • ...


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

Кстати, вот официальный сайт: nxweb.org. Работает на nxweb + своя CMS на Python. Там, правда, в русской версии практически ничего не написано, но в английской есть несколько статей для быстрого старта.
UFO just landed and posted this here
Из обработчика, работающего в отдельном потоке (worker thread), в т.ч. Python, это пока не реализовано. Worker должен вернуть серверу весь ответ целиком.

Для асинхронных модулей на C такого ограничения нет, но написание асинхронных модулей – задача нетривиальная. Нужно интегрироваться в event loop сервера. В т.ч. нужно асинхронно мониторить источник информации, сигнализирующий о необходимости отправки клиентам новых пакетов данных.
Встроенный python. Интересно. Означает ли это, что nxweb может запускать django приложения? Если да, то через какой handler?
Да, Django работает.

Вот тут посмотрите пример для Flask, Django будет отличаться лишь параметром:

"wsgi_application": "hello.app" // full python name of WSGI entry point
а keep-alive поддерживается? что-то nxweb.org с ним не дружит =(
Не может быть. Как проверяли?
ab -n 100 -k -c 10 nxweb.org
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, www.zeustech.net
Licensed to The Apache Software Foundation, www.apache.org

Benchmarking nxweb.org (be patient)...apr_pollset_poll: The timeout specified has expired (70007)
Total of 10 requests completed

если вырубить, не дожидаясь таймаута:
ab -n 100 -k -c 10 nxweb.org
ab -n 100 -k -c 10 nxweb.org
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, www.zeustech.net
Licensed to The Apache Software Foundation, www.apache.org

Benchmarking nxweb.org (be patient)...^C

Server Software: nxweb/3.3.0-dev
Server Hostname: nxweb.org
Server Port: 80

Document Path: /
Document Length: 1199 bytes

Concurrency Level: 10
Time taken for tests: 3.558 seconds
Complete requests: 10
Failed requests: 2
(Connect: 0, Receive: 0, Length: 2, Exceptions: 0)
Non-2xx responses: 10
Keep-Alive requests: 10
Total transferred: 236160 bytes
HTML transferred: 231922 bytes
Requests per second: 2.81 [#/sec] (mean)
Time per request: 3557.915 [ms] (mean)
Time per request: 355.791 [ms] (mean, across all concurrent requests)
Transfer rate: 64.82 [Kbytes/sec] received

Connection Times (ms)
min mean[±sd] median max
Connect: 3 3 0.2 3 4
Processing: 14 39 22.7 58 64
Waiting: 14 39 22.7 58 64
Total: 17 42 22.7 62 67

ApacheBench стар как мир, он использует HTTP 1.0 и, похоже, не понимает chunked-encoding.

Строго говоря, nxweb не должен был бы использовать chunked encoding для клиента, обращающегося по HTTP 1.0, так как chunked encoding – это особенность HTTP 1.1. Пожалуй, это недочет. Не уверен, правда, что мне хочется его исправлять. Ведь живые клиенты, использующие HTTP 1.0, сейчас уже практически не встречаются.

Хотя, я еще подумаю над этим.

nxweb (да и другие серверы) использует chunked encoding не всегда, а только в случаях, когда размер ответа не известен заранее. Обычно это означает, что контент формируется на лету с помощью SSI или шаблонов.

Попробуйте вот так:
ab -n 100 -c 10 -k http://nxweb.org/i/images/wait.gif
UFO just landed and posted this here
Принцип работы веб-сервера прост, и реализовать его несложно. Есть работающие примеры буквально из 100 строк кода. Но, как хорошо видно из Вашего поста, нюансов там несметное множество. А если захочется сделать на собственном сервере полноценный веб-сайт (со статикой, бекендом, SSI, gzip-компрессией, кешированием, ...) то придется много еще чего доделать. Вот так и я, начал с самого простого, в итоге за несколько лет пришел к тому, что есть сейчас.
О безопасности история умалчивает.
Безопасность – штука многогранная…

Сайты, работающие на nxweb, уже не раз бывали под DDoS'ом – успешно его отбивали (хотя DDoS тоже бывает разный), в т.ч. благодаря кешированию. Не знаю, пытались ли их взломать, но и не слышал о том, чтобы это кому-то удалось.

Разумеется, я думал о безопасности, когда писал код, но уязвимости можно найти всегда в любом коде. Обязательно их устраню, когда обнаружатся.
UFO just landed and posted this here
> Те превратить kqueue() в epoll() может любой дурак, тут ума совсем не надо.
В современном ядре Linux epoll обладает практически всеми фичами kqueue (за исключением, пожалуй EVFILT_PROC). Конечно, иногда это происходит ценой написания большего количества кода, но результат получается весьма достойным.
Кстати, использование timerfd для таймеров говорит о том, что не каждый дурак способен способен реализовать таймеры эффективно: в реальных приложениях, как правило, нужны таймеры, срабатывающие через равные промежутки времени, что можно сделать за O(1) в отличие от бездумного использования heap'ов для всего и вся.

>но вот отдачи много: 2-16 мегабит в одно соединение. И куча таких вот соединение, «проксирование» IPTV потоков один-к-многим
Я абсолютно не сведущ в FreeBSD-специфичных API, но как раз для этого в Linux завезли: a) splice (-30% cpu load при проксировании «один к одному») б) vmsplice (для отдачи кучи мегабит из одного соединения, для мультиплексирования) в) tee (для мультиплексирования «с трюкачествами»)
UFO just landed and posted this here
>Про timerfd и heap~ы не понял, можно развернуть мысль?
Как правило, все таймеры можно объединить в heap (по-русски это вроде «пирамидой» называют). Однако, если таймерами управляет приложение, оно может объединить равноинтервальные таймеры в связанный список, привязанный к единственному элементу heap-а. В итоге rearm таймера будет иметь сложность O(1) вместо логарифмических вставки/удаления в heap. Именно поэтому я весьма скептически отношусь к помещению десятков тысяч таймеров в kqueue.

>Меня вот напрягло что запись+чтение могут придти разом, и udata для них никак не разделяется, этот код я так и не отладил, оставив рабочим вариантом когда один описатель — один тип событий.
Хранить в udata файловый дескриптор, а в userspace к файловому дескриптору привешивать цепочки watcher'ов, как это сделано в libev

>Кстати, sendfile() в линухе тоже весь такой обрезанный: не умеет данные до/после файла из буферов посылать
Но зачем? TCP_CORK + send/writev. Зачем плодить лишние сущности которые делают то же, что уже существующие? Цена syscall-а не такая высокая, как это многим кажется.
UFO just landed and posted this here
Не думали написать полноценную статью на эту тему? Похоже вы прилично успели в этом покапаться.

  • epoll/kqueue — возможности, особенности, etc
  • libev, libevent, libuv — сравнение, производительность, etc
  • в целом разработка хайлоад сетевого сервиса: архитектуры, «подводные камни», etc

Мало кто копал в этой теме, инфа скудная. Каких-то сравнительных тестов или анализа разных подходов, как по типам архитектур серверов, так и по используемым библиотекам и системным возможностям — просто нет.
спасибо за статью, она подвигла меня задуматься об оптимизации своего кода
Sign up to leave a comment.

Articles