@moneylender

Какой сервер выбрать для отдачи статики в большом количестве?

Здравствуйте! Возник вопрос, какой лучше сервер выбрать для работы по отдачи статики JS и CSS.
Размеры файлов от 1кб. до нескольких мегабайт.

Требования:
1. Стабильно держать большое (огромное) количество соединений.
2. Занимать мало памяти (это паранойя).
3. Сжимать данные перед отправкой (Возможно, часто используемое держать в кэше).
4. Высокая скорость ответа сервера.

Читаю второй день холиварные темы на форумах, но так и не нашел людей, кого бы беспокоила быстрая реакция (скорость соединения) сервера. Как я понял, Apache после кастрации вполне может быть рассмотрен как кандидат, правда ли это?

Буду рад любому дельному совету по настройке сервера под такие задачи.
  • Вопрос задан
  • 1578 просмотров
Решения вопроса 4
LittleFatNinja
@LittleFatNinja
горе девелопер, любитель лютой садомии
sim3x
@sim3x
nginx!
Ответ написан
Комментировать
@xbox
Как уже много раз написали, использовать нужно nginx. На мой взгляд здесь без вариантов. Про apache забудьте.

По сжатию на лету опция
gzip on;
nginx.org/ru/docs/http/ngx_http_gzip_module.html
Степень сжатия не ставьте максимальную.
Оптимальная степень сжатия 4-5. Иначе процессор сильнее нагружается, а в процентном отношении файл сжимается меньше.
gzip_comp_level 4;

Но если файлы не меняются, или меняются не часто, самый лучший вариант использовать опцию
gzip_static on;
nginx.org/ru/docs/http/ngx_http_gzip_static_module.html
Она позволяет отдавать вместо обычного файла, сжимаемого на лету, предварительно сжатый файл с таким же именем и с расширением “.gz”
С некоторым интервалом запускаете скрипт, который нужно будет написать, и который будет сжимать все файлы с расширением CSS и JS. При этом скрипт может сжимать файлы с максимальной степенью сжатия. После этого nginx будет сразу отдавать сжатые файлы. Процессор вообще при этом нагружаться не будет и скорость еще дополнительно возрастет.

А еще лучше в скрипте перед сжатием для gzip_static запускать какой-нибудь обработчик, который будет вырезать все комментарии, пробелы и тп из CSS и JS файлов. Это дополнительно уменьшит размер несжатых файлов и сжатых файлов и ускорит их разборку на машине клиента. При этом оригиналы CSS и JS без изменений.
Обрезанная и сжатая копия их будет храниться в gz файлах.

У себя я настроил так скрпиты:
Они похожие, но одан вариант просто сжимает файлы (TXT итп), а второй вариант перед сжатием их обрабатывает, удаляя комментарии итп (файлы JS и CSS)

ПЕРВЫЙ ВАРИАНТ (ТОЛЬКО СЖАТИЕ)

/root/scripts/gzip-compress/compress.sh
#! /bin/sh

EXTENSIONS="txt|htm|html|xml|yml|htc|ico"

if [ -z "$1" ]; then
    DIR="`pwd`"
else
    DIR="$1"
fi

find $DIR -type f -regextype posix-egrep -regex ".*\.($EXTENSIONS)\$" -exec `dirname $0`/do-compress.sh '{}' \;

/root/scripts/gzip-compress/do-compress.sh
#! /bin/sh

MINSIZE=100
GZIP="gzip -9 -c"
AWK=awk
TOUCH=touch
CHOWN=chown
CHMOD=chmod

if [ -n "$1" ]; then
    GZ_NAME="$1.gz"
    DATA_PLAIN=`stat --format "%s %Y" "$1"`
    PLAIN_SIZE=`echo "$DATA_PLAIN" | $AWK '{ print $1}'`
    PLAIN_MTIME=`echo "$DATA_PLAIN" | $AWK '{ print $2}'`

    if [ $PLAIN_SIZE -lt $MINSIZE ]; then
		echo "$1 -  Ignoring file: its size ($PLAIN_SIZE) is less than $MINSIZE bytes"
        exit 0;
	fi
	
    if [ -f "$GZ_NAME" ]; then
		GZIPPED_MTIME=`stat --format "%Y" "$GZ_NAME"`
        if [ $GZIPPED_MTIME -eq $PLAIN_MTIME ]; then
			echo "$1 -  Ignoring file: already exist with the same mod time"
            exit 0
		fi
	fi
	
    $GZIP "$1" > "$GZ_NAME"
    $TOUCH -r "$1" "$GZ_NAME"
	
	 $CHOWN --reference="$1" "$GZ_NAME"
     $CHMOD 640 "$GZ_NAME"
	 
    echo "Compressed $1 to $GZ_NAME"
	fi

ВТОРОЙ ВАРИАНТ (СЖАТИЕ С ПРЕДВАРИТЕЛЬНОЙ ОБРАБОТКОЙ С ПОМОЩЬЮ yui-compressor)

/root/scripts/gzip-compress/compress-js-css.sh
#! /bin/sh

EXTENSIONS="css|js"


if [ -z "$1" ]; then
    DIR="`pwd`"
else
    DIR="$1"
fi

find $DIR -type f -regextype posix-egrep -regex ".*\.($EXTENSIONS)\$" -exec `dirname $0`/do-compress-js-css.sh '{}' \;

/root/scripts/gzip-compress/do-compress-js-css.sh
#! /bin/sh

MINSIZE=100
JV="java -jar /usr/share/yui-compressor/yui-compressor.jar"
GZIP="gzip -9 -c"
AWK=awk
TOUCH=touch
CHOWN=chown
CHMOD=chmod

if [ -n "$1" ]; then
    GZ_NAME="$1.gz"
    DATA_PLAIN=`stat --format "%s %Y" "$1"`
    PLAIN_SIZE=`echo "$DATA_PLAIN" | $AWK '{ print $1}'`
    PLAIN_MTIME=`echo "$DATA_PLAIN" | $AWK '{ print $2}'`
	

    if [ $PLAIN_SIZE -lt $MINSIZE ]; then
		echo "Ignoring file $1: its size ($PLAIN_SIZE) is less than $MINSIZE bytes"
        exit 0;
	fi
	
    if [ -f "$GZ_NAME" ]; then
		GZIPPED_MTIME=`stat --format "%Y" "$GZ_NAME"`
        if [ $GZIPPED_MTIME -eq $PLAIN_MTIME ]; then
		echo "$1 -  Ignoring file: already exist with the same mod time"
			exit 0	
		fi
	fi
	
    $JV "$1" | $GZIP  > "$GZ_NAME"
    $TOUCH -r "$1" "$GZ_NAME"
	
	 $CHOWN --reference="$1" "$GZ_NAME"
     $CHMOD 640 "$GZ_NAME"
	 
	 
 echo "Compressed $1 to $GZ_NAME"
 
fi

Чтобы второй вариант работал на сервер нужно установить yui-compressor
yui.github.io/yuicompressor
На debian yui-compressor устанавливается так:
apt-get install yui-compressor

Запускать срипты из крона примерно так:
/etc/crontab
53 4 * * * root nice -n 19 ionice -c2 -n7   /root/scripts/gzip-compress/compress-js-css.sh /var/www/папка_которую/обработать

Данная команда запускает скрипт по сжатию JS и CSS каждый день в 4:53 утра с правами пользователя root. Можно запускать от имени другого пользователя, если все файлы и папки, которые обрабатываются доступны этому пользователю.
Обратите внимание, на всякий случай я запускаю эту команду с низким приоритетом, чтобы при большом количестве файлов эта операция отдавала приоритет ресурсов другим приложениями.
Низкий приоритет процессора
nice -n 19
Низкий приоритет по жесткому диску
ionice -c2 -n7

Без приоритета ту же команду в кроне можно запускать так:
53 4 * * * root   /root/scripts/gzip-compress/compress-js-css.sh /var/www/папка_которую/обработать

Если меняются какие-то оригиналы файлов, для которых предварительно подготовлена gz копия для отдачи сервером nginx, то достаточно удалить gz копию файла и nginx будет отдавать свежий файл. А скрипт, запускаемый по крону, через некоторое время заново создаст gz копию измененного файла.
Ответ написан
Комментировать
@inkvizitor68sl
Linux-сисадмин с 8 летним стажем.
nginx.
Сжатие - gzip, тут нечего придумывать.
Воркеров побольше (а не по количеству ядер), если там ничего больше крутиться не будет.

Кешировать статику в память он тоже умеет - wiki.nginx.org/HttpCoreModule#open_file_cache (только это должны быть неизменяемые файлы - ну или придется привыкать к тому, что файлы обновляются у клиентов не сразу).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
kuroneco
@kuroneco
Системный администратор
nginx, оно заточено под статику.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы