Для начала расскажу, как обычно работают сервера:

  1. Создаётся сокет, который слушает порт
  2. Вызывается системный вызов accept, который берёт первого клиента из очереди соединений, а если его нет – то блокирует приложение до тех пор, пока он не появится
  3. Приложение что-то делает с этим клиентом и в конце концов с ним прощается
  4. goto пункт два

nginx и lighttpd использует вместо accept функции select/kevent/epoll, которые позволяют работать со многими клиентами одновременно, но это уже отдельная история (к асинхронным веб-серверам accept-фильтры применимяются точно так же)

Accept-фильтры – это модули ядра FreeBSD, которые не говорят, что сокет готов до тех пор, пока не выполнится какое-то условие. Я нашёл только два фильтра:

  • dataready – accept блокирует сокет до тех пор, пока в него прийдут данные. Когда мы получаем сокет, мы уже точно можем из него что-то считать
  • httpready – сокет блокируется до тех пор, пока не прийдёт полный GET/HEAD запрос. Соответственно, нам не надо тратить время на переключение контекста, если запрос ещё не собрался.

Остановимся на фильтре httpready

Буферизирует он только GET и HEAD запросы, так как в POST/PUT может прийти 600мегабайтный порнофильм.
Итак, подключаем модуль accf_http:

    kldload accf_http
    echo 'accf_http_load=”YES”' >> /boot/loader.conf

Далее нужно изменить работу с сокетом — установить опцию httpready:

        struct accept_filter_arg afa;
        bzero(&afa, sizeof(afa));
        strcpy(afa.af_name, "httpready");
        setsockopt(sok, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));

Результаты тестов

Так как существует мнение, что accept-фильтры бесполезны, мы решили провести тестирование. Веб-сервер был выбран AnyEvent::HTTPD, клиент – ab. Итак, результаты:

  1. локальная машина, 10000 запросов, concurrency = 4: httpready даёт прирост в 10%
  2. локальная сеть, 10000 запросов, concurrency=1000: httpready даёт прирост в 10%
  3. локальная сеть, 10000 запросов, concurrency = 4: прирост в 25%
  4. локальная сеть, 1000 запросов, concurrency = 1: в два раза!

В боевых условиях, при наличии GPRS, 256k и прочего позора цивилизации, скорость ещё увеличится.

Настройка веб-серверов

В apache 1.3+ и nginx accept-фильтры поддерживаются.

Apache под FreeBSD изначально содержит такую конфигурацию:

 AcceptFilter http httpready
 AcceptFilter https dataready

и менять её не стоит.
А вот в настройках сервера nginx стоит добавить опцию

    accept_filter "httpready";

Ссылки

One Response to “Ускоряем свой HTTP-сервер”

  1. Спасибо, очень интересно.

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

© 2012 Андрей Костенко Suffusion theme by Sayontan Sinha