Оптимизация web сервера

Краткое введение

Схема работы в обычном (чаще всего встречаемом виде) - один web-сервер (судя по статистике инета = 55% apache) отдает все файлы, независимо от их природы и типа. Так для любого css, js, статичного jpg, gif, или png файла (который допустим составляет дизайн нашего сайта) будет отработан полный цикл запроса веб-сервера. В технической литературе для обозначения вспомогательных файлов используют термин frontend, а для скриптов backend. Apache хорош в связке с mod_auth mod_php mod_rewrite, и для того, чтобы отдать общедоступные статичные файлы совсем не обязательно дергать многоуважаемый apache со всеми его модулями (которые нужны чтобы работали скрипты сайта), для этого попробуем без внесения значительных изменений в скрипты сайта(ов) "скинуть" отдачу статики другому

веб-серверу, лучше всего, думаю, nginx. Есть два способа решения этой проблемы, причем их можно использовать одновременно:

  1. Scheme 1: nginx "разбивает" трафик на основании регулярного выражения, проверяющего расширение запрашиваемого файла, и отсылает либо вышестоящему серверу, либо возвращая контент.Scheme 1: nginx "разбивает" трафик на основании регулярного выражения, проверяющего расширение запрашиваемого файла, и отсылает либо вышестоящему серверу, либо возвращая контент. Путь через другой порт. - если у вас доступна одна площадка, и соответсвенно на ней один 80 порт на котором будет работать nginx, отдавая frontend и проксируя backend на основной web-сервер.
    Этот вариант наиболее удобен при уже готовом проекте.
  2. Scheme 2: Работая по второй схеме, nginx только отдает контент, разделение трафика происходит за счет разделения ссылок.Scheme 2: Работая по второй схеме, nginx только отдает контент, разделение трафика происходит за счет разделения ссылок.Путь через другое доменное имя. - если доступна другая площадка, на которую можно сослать поддомен (например img.domain.com, css.domain.com, stt.domain.com) и 80 порт будет по умолчанию на той и на этой площадках для веб-серверов :). Этот вариант более затратен, но дает схему, где nginx занят только отдачей статического контента.

Установка nginx.

На kubuntu 7.10 установка, наверно, чаще всего для меня начинается с репозиториев :) и установка nginx, как обычно, тривиальна и скучна:
$ apt-get install nginx. Однако, при настройке пакета мне было сказано, что, мол, nginx не смог стартовать. Скорее всего, из-за нерабочей конфигурации пакета по-умолчанию (на 80 порт например уже повешен apache). Однако, стандартный конфиг даже не пришлось править, а вот посмотреть на /etc/nginx/sites-available/default стОило. По аналогии будем делать свой конфиг.

Исход

Имеется apache сервер с виртуальным хостом на *:80 domain.com и DocumentRoot /var/www/domain.com/

Вариант №1:

Останавливаем apache, в /etc/apache2/sites-available/* прописываем везде 88 вместо 80. Запускаем apache, проверям:

$ netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp6       0      0 :::88                   :::*                    LISTEN

Если все хорошо, настраиваем nginx: /etc/nginx/sites-available/domain.com

server {
  listen  domain.com:80;
  server_name  domain.com;
  location / {
    proxy_pass         http://domain.com:88/;
  #proxy_pass         http://127.0.0.1:88/;
    proxy_redirect     on;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
  #proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    client_max_body_size       10m;
    client_body_buffer_size    128k;
    client_body_temp_path      /var/nginx/client_body_temp;
    proxy_connect_timeout      90;
    proxy_send_timeout         90;
    proxy_read_timeout         90;
  #proxy_send_lowat           12000;
    proxy_buffer_size          4k;
    proxy_buffers              4 32k;
    proxy_busy_buffers_size    64k;
    proxy_temp_file_write_size 64k;
    proxy_temp_path            /var/nginx/proxy_temp;
    root   /var/www/nginx-data/;
    index  index.html index.htm;
    }
  location ~ \.(css|swf|jpg|png|gif|js|jpeg|mpg|mpeg|wmv|avi|flv)$ {
    root   /var/www/nginx-data/;
    access_log /var/log/nginx/static.log;
    valid_referers none blocked server_names *.domain.com/;
    if ($invalid_referer) {
      return 403;
    }
    expires      30d;
  }
}

Как видно у нас есть место для маневра, например вышестоящий сервер может быть указан как 127.0.0.1 (если apache на этой же площадке), так и доменным именем. Также папка файлов сайта указана как /var/www/nginx-data/, но ничто не мешает сделать ее /var/www/domain.com/, или (я предпочитаю) сделать символическую ссылку на /var/www/domain.com/

$ sudo /etc/init.d/nginx start
# netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.0.0.1:80            0.0.0.0:*               LISTEN
tcp6       0      0 :::88                   :::*                    LISTEN

Вариант №2

Тут основной момент с том, что система сайта должна уметь отдавать ссылки на статический контент с настраиваемым префиксом — URI сервера статики (http://img.domain.com/). Я пока не видел (если кто знает отметьте в комментариях, исправлю) ни одной системы позволяющей это делать (хотя особо не искал эту фичу). Простым выходом (без затрагивания самой системы) является включение в .htaccess правила для перенаправления статики на сервер статики, однако этот вариант не снимет нагрузку самих запросов к апачи.

Результаты

Бенчмарк.... то с 20ти секунд до 9ти, то апачи грузит за 5 секунд, а nginx за 6 :)
В общем, вот показания счетчика времени в том или ином виде отдающего главную страницу сайта в разных средах:
Apache
Firefox 161 запросов 979 KB (0 b from cache) 34.78s
Opera 5s
daiquiri 306 запросов 1311960 байт 147,61s

nginx + apache
Firefox 183 requests 740 KB (0 b from cache) 9.08s
Opera 3s
daiquiri 306 запросов 1203495 байт 3,21s

кстати, daiquiri не умеет "из коробки" тестировать nginx - дело в том...