Исключить себя из статистики Яндекс.Метрики

При установке Яндекс.Метрики на новые и еще не раскрученные сайты, из-за низкой посещаемости собственные визиты на сайт сильно искажают реальную статистику посещений. Для того что бы иметь точные данные, нам необходимо исключить себя из общей статистики посещений.

Для этих целей в Яндекс.Метрике есть специальные фильтры, позволяющие не учитывать посетителей по указанному ip или диапазону адресов. Для того что бы добавить новый фильтр необходимо зайти в панель управления сайтом, после чего переходим в меню Настройки — Фильтр. После чего необходимо выбрать опцию «Не учитывать мои визиты» и добавить соответствующие параметры фильтрации.

Как вариант, можно сделать собственный фильтр адресов на стороне сервера. Данный метод хорошо подойдет как для Яндекс.Метрики так и для других сервисов оценки посещаемости сайтов. Для этого необходимо добавлять код счетчика в тело HTML документа только для тех посетителей, ip которых не попадает под заданный нами фильтр адресов. Для этого необходимо добавить в PHP шаблон страницы следующий код:

<?php if ( $_SERVER["REMOTE_ADDR"] != '127.0.0.1' ): ?>
// Код счетчика
<?php endif; ?>

Изменение часового пояса в Linux

Дата: 12.09.2015Метки:

Как правило, на Linux-серверах для настройки аппаратных часов используют время установленное по Гринвичу. Во время загрузки, Linux синхронизирует время с аппаратными часами с учетом сдвига для конкретной временной временной зоны. Абсолютное большинство программ в процессе работы используют время системных часов. После установки нового сервера важно указать правильные настройки часового пояса.

Делаем резервную копию файла с текущими настройками:

mv /etc/localtime  /etc/localtime-old

Создаем символическую ссылку на необходимый нам timezone:

ln -sf /usr/share/zoneinfo/Europe/Nederlands /etc/localtime

Для того чтобы убедиться что системное время соответствует выбранному часовому поясу, необходимо выполнить команду date. Результат выполнения команды:

Sat Sep 12 14:01:37 EEST 2015

Как вариант для изменения часового пояса в Debian можно использовать специальную утилиту. Для этого в терминале необходимо выполнит следующую команду:

dpkg-reconfigure tzdata

На экране появится псевдографический интерфейс, в котором необходимо выбрать регион и город.

Установка PHP 7 из исходников в Debian

Дата: 12.09.2015Метки:

Материал устарел, для установки PHP 7 читайте Установка PHP 7 в Debian 8.

Существенным аргументом в ползу перехода на PHP 7 является значительное увеличение производительности. Несмотря на отсутствие встроенного JIT-компилятора, в большинстве тестов PHP 7 удалось обогнать по производительности HHVM — транслятор исходного кода, специально созданный компанией Facebook для высокой производительности с целью экономии ресурсов серверов.

На протяжении разработки PHP 5, разработчикам с каждой новой версией удавалось добиться увеличения производительности. Но ближе к PHP 5.5 дальнейшее развитие сдерживала система выделения и освобождения памяти. В течении около пяти месяцев велась работа по рефрактору и изменению ядра, результаты работы получили кодовое имя phpng, так же известном как Zend Engine 3.

На момент написания записи доступен релиз кандидат PHP 7 RC2, финальная версия должна выйти в октябре этого года. На данный момент PHP 7 нет в стандартных репозиториях Debian, поэтому для установки PHP 7 его необходимо собирать исходников.

Для начала нам необходимо установить все необходимые для сборки PHP 7 пакеты:

apt-get install git-core cmake gawk libmysqlclient-dev 
  libxml2-dev libmcrypt-dev libicu-dev openssl build-essential binutils-dev 
  libcap-dev zlib1g-dev libtbb-dev libonig-dev libpcre3-dev 
  autoconf libtool libcurl4-openssl-dev wget memcached 
  libreadline-dev libncurses5-dev libmemcached-dev libbz2-dev 
  libc-client2007e-dev php5-mcrypt php5-imagick libgoogle-perftools-dev 
  libcloog-ppl-dev libelf-dev libdwarf-dev libunwind8-dev subversion 
  libtbb2 g++-4.8 gcc-4.8 libjemalloc-dev 
  libc6-dev libmpfr4 libgcc1 binutils 
  libc6 libc-dev-bin libc-bin libgomp1 
  libstdc++-4.8-dev libstdc++6 
  libarchive13 cmake-data libacl1 libattr1 
  g++ cpp gcc make libboost-thread1.55.0 
  libboost-thread-dev libgd2-xpm-dev 
  pkg-config libboost-system1.55-dev libboost-context1.55-dev 
  libboost-program-options1.55-dev libboost-filesystem1.55-dev libboost-regex1.55-dev 
  libmagickwand-dev libiberty-dev libevent-dev libxslt-dev libgoogle-glog-dev 
  automake libldap2-dev libkrb5-dev libyaml-dev gperf ocaml-native-compilers 
  libgmp-dev libgmp3-dev
ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h

Скачиваем и распаковываем исходники PHP 7:

mkdir /tmp/php7 && cd /tmp/php7
wget https://downloads.php.net/~ab/php-7.0.0RC2.tar.gz
tar -xzf php-7.0.0RC2.tar.gz
mv php-7.0.0RC2 php-src

Минимальный набор компонентов PHP 7, необходимый для работы WordPress:

cd php-src
./buildconf --force
CONFIGURE_STRING="--prefix=/usr/local/php7 
--enable-fpm 
--enable-mysqlnd 
--enable-mbstring 
--enable-sockets 
--disable-ipv6 
--with-config-file-scan-dir=/usr/local/php7/etc/conf.d 
--with-curl 
--with-gd 
--with-fpm-user=www-data 
--with-fpm-group=www-data 
--with-mysql-sock=/var/run/mysqld/mysqld.sock 
--with-mysqli=mysqlnd 
--with-openssl 
--with-zlib 
--without-sqlite3 
--without-pdo-sqlite"

Компилируем PHP 7:

mkdir /usr/local/php7
./configure $CONFIGURE_STRING
make && make install

Создаем каталог для конфигурационных файлов PHP 7:

mkdir /usr/local/php7/etc/conf.d

Создаем символическую ссылку php-fpm для php7-fpm

ln -s /usr/local/php7/sbin/php-fpm /usr/local/php7/sbin/php7-fpm

Добавляем конфигурационные файлы:

cd /tmp/php7
cp php-src/php.ini-production /usr/local/php7/lib/php.ini
# nano /usr/local/php7/etc/php-fpm.d/www.conf

[www]

user = www-data
group = www-data

listen = /var/run/php7-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
# nano /usr/local/php7/etc/php-fpm.conf

[global]

pid = /var/run/php7-fpm.pid
error_log = /var/log/php7-fpm.log

include=/usr/local/php7/etc/php-fpm.d/*.conf
# mkdir /usr/local/php7/etc/conf.d/
# nano /usr/local/php7/etc/conf.d/modules.ini

# Zend OPcache
zend_extension=opcache.so

Добавляем PHP-FPM в автозагрузку:

# nano /etc/init.d/php7-fpm

#!/bin/sh
### BEGIN INIT INFO
# Provides:          php7-fpm
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts php7-fpm
# Description:       Starts The PHP FastCGI Process Manager Daemon
### END INIT INFO

# Author: Ondrej Sury <ondrej@debian.org>
# Adjusted for PHP7 by Kaspars Dambis <hi@kaspars.net>

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/php7/sbin
DESC="PHP7 FastCGI Process Manager"
NAME=php7-fpm
DAEMON=/usr/local/php7/sbin/$NAME
CONFFILE=/usr/local/php7/etc/php-fpm.conf
DAEMON_ARGS="--daemonize --fpm-config $CONFFILE"
CONF_PIDFILE=$(sed -n 's/^pid[ =]*//p' $CONFFILE)
PIDFILE=${CONF_PIDFILE:-/var/run/php7-fpm.pid}
TIMEOUT=30
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# Don't run if we are running upstart
if init_is_upstart; then
    exit 1
fi

#
# Function to check the correctness of the config file
#
do_check()
{
    # Run php-fpm with -t option to check the configuration file syntax
    errors=$($DAEMON --fpm-config $CONFFILE -t 2>&1 | grep "[ERROR]" || true);
    if [ -n "$errors" ]; then
        echo "Please fix your configuration file..."
        echo $errors
        return 1
    fi
    return 0
}

#
# Function that starts the daemon/service
#
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null 
		|| return 1
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- 
		$DAEMON_ARGS 2>/dev/null 
		|| return 2
	# Add code here, if necessary, that waits for the process to be ready
	# to handle requests from services started subsequently which depend
	# on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred
	start-stop-daemon --stop --quiet --retry=QUIT/$TIMEOUT/TERM/5/KILL/5 --pidfile $PIDFILE --name $NAME
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	# Wait for children to finish too if this is a daemon that forks
	# and if the daemon is only ever run from this initscript.
	# If the above conditions are not satisfied then add some other code
	# that waits for the process to drop all resources that could be
	# needed by services started subsequently.  A last resort is to
	# sleep for some time.
	start-stop-daemon --stop --quiet --oknodo --retry=0/30/TERM/5/KILL/5 --exec $DAEMON
	[ "$?" = 2 ] && return 2
	# Many daemons don't delete their pidfiles when they exit.
	rm -f $PIDFILE
	return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
	#
	# If the daemon can reload its configuration without
	# restarting (for example, when it is sent a SIGHUP),
	# then implement that here.
	#
	start-stop-daemon --stop --signal USR2 --quiet --pidfile $PIDFILE --name $NAME
	return 0
}

case "$1" in
    start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_check $VERBOSE
	case "$?" in
	    0)
		do_start
		case "$?" in
		    0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		    2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
		esac
		;;
	    1) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
    stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
    status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
    check)
        do_check yes
	;;
    reload|force-reload)
	log_daemon_msg "Reloading $DESC" "$NAME"
	do_reload
	log_end_msg $?
	;;
    reopen-logs)
	log_daemon_msg "Reopening $DESC logs" $NAME
	if start-stop-daemon --stop --signal USR1 --oknodo --quiet 
	    --pidfile $PIDFILE --exec $DAEMON
	then
	    log_end_msg 0
	else
	    log_end_msg 1
	fi
	;;
    restart)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
    *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload|force-reload}" >&2
	exit 1
    ;;
esac

:
chmod +x /etc/init.d/php7-fpm
update-rc.d php7-fpm defaults

Для работы PHP-FPM через сокет необходимо необходимо внести изменения в файл:

nano /usr/local/php7/etc/php-fpm.d/www.conf

Вместо настройки параметров порта, необходимо добавить следующие строки:

listen = /var/run/php7-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Для запуска PHP7-FPM необходимо выполнить следующую команду:

service php7-fpm start

Nginx: an upstream response is buffered to a temporary file

Дата: 26.08.2015Метки:

Данное предупреждение можно увидеть в логах Nginx при работе в связке с PHP-FPM:

[warn] 3400#3400: *21 an upstream response is buffered to a temporary file /var/cache/nginx/fastcgi_temp/1/00/0000000001 while reading up

Проблема вызвана недостаточным размером буфера Nginx, связи с чем для передачи полученных от PHP данных, Nginx предварительно записывает их во временный файл на диске.

Исправить: an upstream response is buffered to a temporary file

Для устранения предупреждения, необходимо увеличить размер буфера в Nginx. Для этого в секцию location ~ .php$, необходимо добавить следующие параметры:

fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;

В итоге должно получится как в примере ниже:

location ~ .php$ {
    try_files $uri = 404;
    fastcgi_pass unix:/var/run/php-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    include fastcgi_params;
}

Подробнее о изменении размера буфера под конкретно ваши условия можно прочитать в этой статье.

Редирект c HTTP на HTTPS в Nginx

Дата: 23.08.2015Метки:

Важным моментом в настройке SSL, является перенаправление всего HTTP-трафика на защищенное HTTPS-соединение. Надежнее всего это реализуется на уровне веб-сервера. Для того что бы принудительно с HTTP переадресовать всех посетителей на защищенное HTTPS соединение, необходимо в Nginx прописать в секцию server 301 редирект:

if ($scheme = http) {
       return 301 https://$server_name$request_uri;
    }
if ($host ~* www.) {
       return 301 https://$server_name$request_uri;
    }

Код статуса 301 означает, что запрашиваемая страница на постоянной основе перемещена на новый адрес. Что касается поисковых систем, то 301 редирект будет сигналом для переноса PR, тИЦ и всей ссылочной массы сайта. В результате, позиции сайта после повторной индексации останутся на прежнем уровне.

Добавляем SWAP в Linux

Дата: 23.08.2015Метки:

При заказе виртуального сервера, часто для установки используется заранее подготовленные шаблоны, из-за чего в системе может отсутствовать SWAP-раздел. Что бы предотвратить ошибки вызванные переполнением RAM и обеспечит нормальное функционирование системы в будущем, необходимо добавить в систему дополнительное SWAP-пространство.

Как правило, в процессе установки под SWAP выделяют отдельный раздел на диске, но начиная с версии ядра Linux 2.6 работа SWAP-файла не уступает по производительности SWAP-разделу. Поэтому, в большинстве случаев я предпочитаю использовать SWAP-файл размещенный в корневом разделе диска. Это добавляет гибкости для обслуживания системы в будущем: я в любой момент с легкостью могу уменьшить или увеличить размер файла, при необходимости перенести на другой раздел или полностью удалить.

Ниже приведен пример скрипта для быстрой настройки SWAP:

if [ -f /swapfile ]; then
    echo "Swapfile already exists?"
    exit 1
fi

dd if=/dev/zero of=/swapfile bs=1G count=2
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
sysctl vm.swappiness=10
sysctl vm.vfs_cache_pressure=50
echo "/swapfile   none    swap    sw    0   0" >> /etc/fstab
echo vm.swappiness=10 >> /etc/sysctl.conf
echo vm.vfs_cache_pressure=50 >> /etc/sysctl.conf

Параметр vm.swappiness указывает системе при каком минимальном проценте свободной памяти необходимо задействовать SWAP. Значение параметра может быть в пределах от 0 — 100. Но для улучшения производительности лучше установит значение данного параметра равным 10.

В случае использования SSD, необходимо уменьшит размер дискового кэша, для этого рекомендуется установить значение параметра vm.vfs_cache_pressure равным 50.

Иногда может возникнуть необходимость очистить SWAP без перезагрузки системы, для этого используем следующую команду:

swapoff -a && swapon -a

Для принудительной очистки системных кэшей используем команду:

sync

# Чистим pagecache:
echo 1 > /proc/sys/vm/drop_caches

# Чистим dentrie и inode кэши:
echo 2 > /proc/sys/vm/drop_caches

# Чистим pagecache, dentrie и inode кэши:
echo 3 > /proc/sys/vm/drop_caches

Как правило, я старюсь перегружать сервер только при крайней необходимости. Одна из причин, по которой я люблю Linux — если не течет память, то система абсолютно не нуждается в перезагрузке. Исключительно в целях профилактики чтобы очистить кеши и SWAP, на всех своих серверах в cron добавляю следующую команду:

0 0 * * * swapoff -a && swapon -a && sync && echo 3 > /proc/sys/vm/drop_caches

Настройка SSL в Nginx

Дата: 20.08.2015Метки:

Ранее я уже описывал процесс установки сертификата StartSSL и приводил пример минимального набора параметров необходимого для использования SSL в Nginx. В этой статье речь пойдет о более тонкой настройке. Сайт, настроенный по рекомендациям в данной статье, проходит проверку SSL на А+.

Если вы используете сертификат от StartSSL, полезную информацию по установке сертификата можно прочитать по ссылке, которая находится в начале статьи. Для сертификатов выданных другими центрами сертификации необходимо выполнить аналогичные действия.

Настройку SSL в Nginx лучше начинать с минимальных рабочих параметров:

server {
    listen 443 ssl;
    server_name domain.net;

    ssl_certificate /etc/nginx/ssl/domain_com/domain.pem;
    ssl_certificate_key /etc/nginx/ssl/domain_com/domain.key;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }
}

Далее привожу краткое описание используемых директив.

Указываем путь к файлу содержащему “связку” из сертификатов: к сертификату сервера мы присоединяем промежуточный сертификат. Важно соблюдать правильную последовательность, иначе во время запуска Nginx вы получите ошибку.

# cat ssl.crt sub.class1.server.ca.pem > domain.pem
ssl_certificate /etc/nginx/ssl/domain.pem;

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

# openssl rsa -in ssl.key -out private.key;
ssl_certificate_key /etc/nginx/ssl/domain.key;

Перезапустим Nginx, если все работает правильно, можно переходить к дальнейшим настройкам.

Для использования набора шифров DHE, необходимо создать ключ Диффи-Хеллмана и указывать путь к файлу в настройка Nginx:

# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

С включенным SSL сервер использует дополнительные ресурсы процессора. Для снижения количества операций необходимо задать размер кэша и время хранения SSL-сессий. В 1 мегабайт кэша помещается около 4000 сессий.

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;

Дополнительно для снижения нагрузки, мы обрабатываем сразу несколько запросов в рамках одного keepalive-соединения:

keepalive_timeout 70;

Указываем поддерживаемые сервером протоколы SSL:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Указываем, что серверные шифры имеют больший приоритет, чем клиентские шифры. Рекомендуемый набор шифров можно взять с официально сайта MozillaWiki. Можно сразу использовать использовать генератор конфига для Nginx.

ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DES";

Для уменьшая время загрузки страниц, разрешаем серверу для валидации сертификата прикреплять OCSP-ответы. Для работы функции необходимо указать путь к файлу сертификата издателя и DNS-сервер.

ssl_stapling on;
ssl_trusted_certificate /etc/nginx/ssl/ca.pem;
resolver 8.8.8.8;

Что бы указать браузеру, что сайт доступен только по HTTPS, необходимо указать заголовок:

add_header Strict-Transport-Security max-age=31536000 always;

Заголовок запрещает браузеру показывать сайт в фрейме:

add_header X-Frame-Options DENY;

Чтобы предотвратить MITM атаки с поддельными сертификатами, указываем заголовок Public-Key-Pins:

add_header Public-Key-Pins 'pin-sha256="base64+info1="; max-age=31536000' always;

Для директивы pin-sha256 используем одну из команд ниже:

openssl rsa  -in domain.key -outform der -pubout | openssl dgst -sha256 -binary | base64
openssl req  -in domain.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64
openssl x509 -in domain.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64

Указываем браузеру что бы он использовал отданный сервером Сontent-type, вместо автоматического его определения:

add_header X-Content-Type-Options nosniff;

Заголовок активирует XSS-защиту:

add_header X-XSS-Protection "1; mode=block";

Используем переадресацию на защищенное соединение:

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        server_name domain.net;
        return 301 https://domain.com;
}

Пример конфигурационного файла:

Влияние GZIP на производительность Nginx

Дата: 16.08.2015Метки:

Использование GZIP в Nginx может создавать сильную нагрузку на процессор и серьезно снизить производительность. Для устойчивой работы веб-сервера под нагрузкой, важно заранее подобрать оптимальные параметры. В процессе приходится искать своего рода компромисс межу степенью сжатия GZIP и производительностью Nginx.

В интернете много информации по настройке GZIP в Nginx. Вместо того что бы слепо полагаться на сухую информацию, я решил проверить на практике влияние сжатия на производительность Nginx. Затем на основе полученных данных выбрать оптимальные настройки.

Для замеров на виртуальной машине под Debian 8.1 была установлена последняя на текущий момент версия Nginx 1.9.3, собранного с параметром --with-http_gzip_static_module. Для тестирования использовался статический HTML-документ с главной страницы моего блога.

Производительности Nginx измерялась утилитой ApacheBench, запущенная со следующими параметрами:

service nginx restart && ab -c 100 -n 25000 -H "Accept-Encoding: gzip,deflate" "http://192.168.1.32/static.html"

Посмотреть полные данные тестирования можно на сайте GitHab. Для лучшей наглядности данные представлены в виде графиков ниже.

Поочередно изменяя значения параметра gzip_comp_level от 1 до 9 запускался ApacheBench. В конце каждого теста записывались данные о количестве обработанных запросов и объеме переданных данных.

Результаты измерений можно увидеть на графике ниже.

Следующий график содержит информацию о количестве переданных данных для различного уровня сжатия.

На последнем графике мы можем сравнить скорость работы Nginx с включенным и отключенным сжатием GZIP и использованием модуля gzip_static.

Исходя из полученных данных, можно сделать вывод о том, что уровень сжатия GZIP существенно влияет на производительность Nginx. На первом графике видно, что разница между максимальным и минимальным значениями достигает почти 2,5 раза.

Производительность операции упирается в ресурсы процессора. Начина с значения параметра gzip_comp_level равным 3, скорость начинает значительно проседать. По сравнению с данными полученными без использования сжатия, дальнейшее увеличение уровня компрессии не приносит существенного результата. Использование степени сжатия больше 6 вовсе не имеет смысла и приносит больше вреда чем пользы.

Дополнительно выполнены замеры для отдачи предварительно сжатых данных.  Результаты показывают, что использования модуля http_gzip_static_module является хорошей альтернативой GZIP сжатию на лету и позволяет существенно увеличить производительность Nginx.

Таким образом, на основе полученных данных можно сделать вывод, что наиболее эффективно будет передавать предварительно сжатые данные с использованием максимального уровнем сжатия. Для сжатия всех имеющихся CSS и JS файлов, необходимо выполнить команду:

for i in `find /home/www/* -type f -name '*.js'`; do echo $i; gzip -c -9 $i > $i.gz; touch -r $i $i.gz; done;
for i in `find /home/www/* -type f -name '*.css'`; do echo $i; gzip -c -9 $i > $i.gz; touch -r $i $i.gz; done;

Для того что бы удалит .gz архивы:

for i in `find /home/www/* -type f -name '*.js.gz'`; do echo $i; rm $i; done;
for i in `find /home/www/* -type f -name '*.css.gz'`; do echo $i; rm $i; done;

Для сжатия динамически создаваемых страниц напротив лучше использовать минимальные параметры уровня сжатия, я рекомендую становить значение параметра gzip_comp_level равным 2.

Рекомендуемые параметры GZIP для Nginx:

gzip on;
gzip_static on;
gzip_comp_level 2;

Установка Nginx с поддержкой HTTP/2

Дата: 14.08.2015Метки:

Завершение разработки протокола HTTP/2 стало первым крупным обновлением HTTP за последние 16 лет. При проектировании HTTP/2 основной фокус был направлен на оптимизацию алгоритмов передачи данных и ускорение загрузки страниц.

В качестве основы для HTTP/2 был взят уже существующий открытый протокол SPDY/3, первую версию которого Google представила в 2009 году. Согласно планам, HTTP/2 должен быстро вытеснить протокол SPDY, став его эволюционным продолжением. Уже в начале 2016 года Google планирует полностью перейти на новый стандарт и отказаться от поддержки SPDY в браузере Chrome.

Недавно была представлен тестовая версия модуля HTTP/2 для Nginx. В данный момент доступна альфа версия патча. Полную поддержку протокола HTTP/2 планируется ввести к концу этого года, а пока все желающие могут протестировать его в своих проектах.

Для сборки Nginx с поддержкой HTTP/2 необходим NGINX 1.9.0 и OpenSSL 1.0.2 или новее.

Добавим в /etc/apt/sources.list официальный репозиторий для mainline-ветки Nginx:

deb http://nginx.org/packages/mainline/debian/ codename nginx
deb-src http://nginx.org/packages/mainline/debian/ codename nginx

Скачиваем и устанавливаем PGP-ключ, затем обновляем индекс пакетов apt:

cd /tmp/ && wget http://nginx.org/keys/nginx_signing.key && apt-key add nginx_signing.key
apt-get update

Скачиваем необходимые для компиляции и сборки пакета программы, устанавливаем зависимости необходимые для Nginx:

apt-get install dpkg-dev
apt-get build-dep nginx

Скачиваем исходники Nginx:

cd /tmp
apt-get source nginx

Страница с патчами HTTP/2 для Nginx. Скачиваем патч HTTP/2 для нашей версии Nginx, проверяем возможность применения и если нет ошибок, по устанавливаем патч:

cd /tmp/nginx-1.9.3
wget http://nginx.org/patches/http2/patch.http2.txt
patch -p1 --dry-run < patch.http2.txt
patch -p1 < patch.http2.txt

Скачиваем и распаковываем исходники OpenSSL:

cd /tmp
wget https://openssl.org/source/openssl-1.0.2d.tar.gz
tar ixzvf openssl-1.0.2d.tar.gz

Перед началом сборки и компиляции необходимо внести изменения в файл:

nano /tmp/nginx-1.9.3/debian/rules

В секциях override_dh_auto_build и configure_debug необходимо удалить строку $(WITH_SPDY) и добавить в конец следующие опции:

--with-http_v2_module 
--with-openssl=/tmp/openssl-1.0.2

Для примера привожу фрагмент с изменениями из моего файла:

override_dh_auto_build:
	dh_auto_build
	mv objs/nginx objs/nginx.debug
	CFLAGS="" ./configure 
		--prefix=/etc/nginx 
		--sbin-path=/usr/sbin/nginx 
		--conf-path=/etc/nginx/nginx.conf 
		--error-log-path=/var/log/nginx/error.log 
		--http-log-path=/var/log/nginx/access.log 
		--pid-path=/var/run/nginx.pid 
		--lock-path=/var/run/nginx.lock 
		--http-client-body-temp-path=/var/cache/nginx/client_temp 
		--http-proxy-temp-path=/var/cache/nginx/proxy_temp 
		--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 
		--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 
		--http-scgi-temp-path=/var/cache/nginx/scgi_temp 
		--user=nginx 
		--group=nginx 
		--with-http_ssl_module 
		--with-http_gzip_static_module 
		--with-threads 
		--with-file-aio 
		--with-cc-opt="$(CFLAGS)" 
		--with-ld-opt="$(LDFLAGS)" 
		--with-ipv6 
		--with-http_v2_module 
		--with-openssl=/tmp/openssl-1.0.2
	dh_auto_build

После чего выполняем компиляцию и сборку deb-пакета:

cd /tmp/nginx-1.9.3
dpkg-buildpackage -rfakeroot -uc -b

После сборки пакета, установим Nginx командой:

dpkg -i nginx_1.9.3-1~jessie_i386.deb

Для включения поддержки HTTP/2 добавьте в конфигурационный файл Nginx вашего сайта параметры ssl и http2 к директивам listen:

server {
    listen 443 ssl http2 default_server;

    ssl_certificate     server.crt;
    ssl_certificate_key server.key;
    ...
}

На момент написания статьи в браузерах не реализована поддержка HTTP/2 без SSL шифрования, поэтому параметр ssl является обязательным. Как вариант — можно создать самоподписанный сертификат.

На данный момент статья частично потеряла свою актуальность, Начиная с версии Nginx 1.9.5 присутствует встроенная поддержка протокола. Информация о том как включить HTTP/2 в Nginx.

Установка Nginx из исходников

Дата: 13.08.2015Метки:

Как правило, в стандартных репозиториях Debian находится устаревшая версия пакета Nginx. Для того чтобы установить последнюю стабильную версию и включить автоматическое обновление пакетов, рекомендуется использовать официальный репозиторий Nginx.

Для более тонкой настройки и выбора модулей, которые войдут в состав сборки, я предпочитаю самостоятельно собирать Nginx из исходников. При необходимости у меня всегда есть проверенный и настроенный под себя deb-пакет Nginx, а в случае каких-либо проблем, всегда есть возможность откатится до предыдущей сборки.

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

Для того что бы не засорять систему ненужными пакетами, компиляцию и сборку deb-пакета я предпочитаю выполнять на виртуальной машине, после чего для установки необходимо просто перенести deb-пакет на сервер.

Для начала необходимо добавить официальный репозиторией Nginx. Для Debian замените codename на кодовое имя дистрибутива, и добавьте в конец файла /etc/apt/sources.list строки:

Для mainline-ветки.

deb http://nginx.org/packages/mainline/debian/ codename nginx
deb-src http://nginx.org/packages/mainline/debian/ codename nginx

Или для стабильной ветки.

deb http://nginx.org/packages/debian/ codename nginx
deb-src http://nginx.org/packages/debian/ codename nginx

Для проверки подлинности подписи репозитория Nginx, скачиваем PGP-ключ и устанавливаем его в связку ключей программы apt:

cd /tmp/ && wget http://nginx.org/keys/nginx_signing.key && apt-key add nginx_signing.key

Для обновления индекса пакетов выполним команду:

apt-get update

Выполним установку необходимых для компиляции и сборки программ, установим все необходимые зависимости для nginx:

apt-get install dpkg-dev
apt-get build-dep nginx
apt-get install libxslt1-dev libgd2-dev libgeoip-dev

На момент написания поста, я использовал последнюю версию nginx-1.9.3. Для сборки deb-пакета скачиваем с официального репозитория исходники Nginx:

cd /tmp
apt-get source nginx

Для того что бы изменить параметры компиляции, добавить или удалить модули Nginx, необходимо отредактировать файл:

nano /tmp/nginx-1.9.3/debian/rules

Нас интересует содержимое секции override_dh_auto_build. Здесь мы можем включить в сборку необходимы нам модули или удалить ненужные. Ниже приведен пример используемой мной конфигурация:

override_dh_auto_build:
	dh_auto_build
	mv objs/nginx objs/nginx.debug
	CFLAGS="" ./configure 
		--prefix=/etc/nginx 
		--sbin-path=/usr/sbin/nginx 
		--conf-path=/etc/nginx/nginx.conf 
		--error-log-path=/var/log/nginx/error.log 
		--http-log-path=/var/log/nginx/access.log 
		--pid-path=/var/run/nginx.pid 
		--lock-path=/var/run/nginx.lock 
		--http-client-body-temp-path=/var/cache/nginx/client_temp 
		--http-proxy-temp-path=/var/cache/nginx/proxy_temp 
		--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 
		--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 
		--http-scgi-temp-path=/var/cache/nginx/scgi_temp 
		--user=nginx 
		--group=nginx 
		--with-http_ssl_module 
		--with-http_gzip_static_module 
		--with-threads 
		--with-file-aio 
		$(WITH_SPDY) 
		--with-cc-opt="$(CFLAGS)" 
		--with-ld-opt="$(LDFLAGS)" 
		--with-ipv6
	dh_auto_build

После того как все необходимы настройки сделаны, можно начинать компиляцию и сборку пакета:

cd /tmp/nginx-1.9.3
dpkg-buildpackage -rfakeroot -uc -b

Если в процессе не было ошибок, в каталоге /tmp мы увидим собранный из исходников deb-пакет nginx_1.9.3-1~jessie_i386.deb. Для его установки необходимо выполнить команду:

dpkg -i nginx_1.9.3-1~jessie_i386.deb

 

Обновление 07.03.16
Начиная с версии Nginx 1.9.11 используется поддержка динамических модулей. Связи с чем в процессе сборки пакета произошли изменения. При отключении некоторых модулей процесс сборки может завершаться ошибкой.