Как экономить трафик на веб-сервере



    Нагруженный веб-проект расходует терабайты трафика. На больших числах экономия в 10-20% может существенно сберечь деньги и помочь не выйти за квоты.
    Что делать, если трафик опасно приближается к лимитам вашего тарифа на хостинге или вовсе выходит за них?

    В этой статье мы разберём основные техники, помогающие сэкономить трафик на веб-сервере.

    Сожми это!


    Самый простой способ сэкономить на трафике — сжать его. Это нагружает процессор сервера, но позволяет быстрее отдавать клиенту данные, уменьшая их размер, чтобы быстрее закрывать соединения. В ходу в основном алгоритмы, совместимые с Deflate, но есть и экзотика.

    Gzip


    Самый распространённый алгоритм сжатия. Сжимает без потерь, с хорошей степенью сжатия (настраивается от 1 до 9, по умолчанию 6) и быстрой распаковкой. Простой и эффективный, подойдёт в большинстве случаев.



    Nginx

    gzip            on;
    gzip_min_length 1000;
    gzip_proxied    expired no-cache no-store private auth;
    gzip_types      text/plain application/xml;

    Apache

    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript

    Zopfli


    Современная альтернатива gzip, сжимает на 3-8% лучше, зато гораздо медленнее (разжимается на клиенте с той же скоростью). Работает на Deflate, поэтому на 100% совместим с zlib, поддержка в браузерах тоже полная.

    git clone https://code.google.com/p/zopfli/
    cd zopfli
    make

    Nginx

    gzip_static     on;

    Brotli


    Как и Zopfli, разработан в недрах Гугла. Умеет сжимать не только в статике, но и на лету, как gzip. В отличие от предыдущих алгоритмов, не только ищет повторы в тексте, но и сразу мапит по своему словарю, в котором много тегов и стандартных кодовых фраз, что крайне эффективно для сжатия html/css/js: если Zopfli даёт около 8% сжатия после gzip, то Brotli способен накинуть ещё около 10-15%, а у кого-то и вовсе 23%! Зато поддерживается только в https и несовместим с zlib/deflate. Caniuse обнадёживает:



    Nginx

    Поддержка в виде стандартного модуля есть только в Plus, обычный Nginx надо собирать со сторонним модулем (--add-module=/path/to/ngx_brotli):

    git clone https://github.com/google/ngx_brotli.git
    git clone https://github.com/bagder/libbrotli.git
    ./autogen.sh
    ./configure
    make
    

    
    cd /path/to/nginx
    ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --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_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' --add-module=/path/to/ngx_brotli
    make

    Конфиг:

    brotli_static	on;

    В динамическом режиме:

    brotli		on;
    brotli_comp_level	6;
    brotli_types	text/plain text/css text/xml application/x-javascript;

    Apache

    Тут всё проще, установить mod_brotli и сконфигурировать модуль:

    <IfModule brotli_module>
     BrotliCompressionLevel 10
     BrotliWindowSize 22
     AddOutputFilterByType BROTLI text/html text/plain text/css text/xml
     AddOutputFilterByType BROTLI text/css
     AddOutputFilterByType BROTLI application/x-javascript application/javascript
     AddOutputFilterByType BROTLI application/rss+xml
     AddOutputFilterByType BROTLI application/xml
     AddOutputFilterByType BROTLI application/json
     </IfModule>

    Закэшируй это!


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

    HTTP-заголовки Cache-control, Expires и Vary позволяют спроектировать очень гибкую политику кэширования, хотя можно и в лоб проставить всюду max-age=2592000.

    Nginx

    location ~* ^.+\.(js|css)$ {
    	expires max;
    }

    Apache

    <ifModule mod_headers.c>
        <FilesMatch "\.(html|htm)$">
            Header set Cache-Control "max-age=43200"
        </FilesMatch>
        <FilesMatch "\.(js|css|txt)$">
            Header set Cache-Control "max-age=604800"
        </FilesMatch>
        <FilesMatch "\.(flv|swf|ico|gif|jpg|jpeg|png)$">
            Header set Cache-Control "max-age=2592000"
        </FilesMatch>
        <FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
            Header unset Cache-Control
        </FilesMatch>
    </IfModule>
    <ifModule mod_expires.c>
        ExpiresActive On
        ExpiresDefault "access plus 5 seconds"
        ExpiresByType image/x-icon "access plus 2592000 seconds"
        ExpiresByType image/jpeg "access plus 2592000 seconds"
        ExpiresByType image/png "access plus 2592000 seconds"
        ExpiresByType image/gif "access plus 2592000 seconds"
        ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
        ExpiresByType text/css "access plus 604800 seconds"
        ExpiresByType text/javascript "access plus 604800 seconds"
        ExpiresByType application/javascript "access plus 604800 seconds"
        ExpiresByType application/x-javascript "access plus 604800 seconds"
        ExpiresByType text/html "access plus 43200 seconds"
        ExpiresByType application/xhtml+xml "access plus 600 seconds"
    </ifModule>

    Распредели это!


    Хороший CDN для загруженного сайта обычно стоит приличных денег, но на первое время хватит и бесплатного. Загрузка тяжелых ресурсов через CDN может уменьшить трафик в несколько раз! Не стоит пренебрегать такой возможностью, особенно когда она условно-бесплатна. Одноразовых статей с топами бесплатных сетей в интернете полно, но на первое место всегда ставят Cloudflare.



    А ещё у них же есть бесплатные Service Workers, на которых можно вручную поднять свой CDN с преферансом и куртизанками. Примеров мало, но туториал есть на официальном портале SW.

    Заключение


    Если вы ещё не используете хотя бы gzip — добро пожаловать в интернет, здесь более 80% сайтов работают с ним. Если стандартного сжатия и -9 вам не хватает, используйте Brotli с бэкапом в виде Zopfli (так как у бротли ещё нет 100% покрытия). На этом можно сэкономить кучу трафика:

    • gzip: 50-95% сжатия в зависимости от контента. В среднем по вебу 65-80%
    • Zopfli: +3-8% сжатия относительно gzip в среднем, но бывает и 10%
    • Brotli: +10-15% сжатия относительно gzip в зависимости от контента c редкими выстрелами до 20% и выше

    image

    Кэшируйте данные на клиенте, это уменьшает трафик при повторных заходах на 99% и ниже, в зависимости от выбранной политики кэширования и изменений на сайте.

    Используйте CDN для доставки контента и базовой балансировки. Основной удар берёт на себя раздающий сервер, в то время как до основного трафик сократится в разы. Насколько именно — зависит от сети, нагрузки и выбранного режима работы.

    Всё вышеперечисленное разворачивается в кратчайшие сроки и не требует сложной перестройки серверной архитектуры, что даёт вам время на её грамотное проектирование. Сжимайте, кэшируйте, распределяйте, и мониторьте свои затраты, чтобы не попасть на большие деньги.

    VDSina.ru
    Серверы в Москве и Амстердаме

    Комментарии 15

      0

      Видел как некоторые сайты на лету переживают JPEG в WEBP, при этом отдают его по той же ссылке но с другим контент-тайпом. По размеру получается почти в два раза меньше при одинаковом качестве. Судя по всему работает это только для Chrome, а значит веб-сервер смотрит на user-agent и в зависимости от этого отдает разные файлы. Может есть готовые решения для такого?

      +1

      А насколько WEBP сжимает фото?

        0
        если картинку png предварительно оптимизировать с помощью сервисов типа tinypng то webp ужимает еще в 3-4 раза. С 200кб до 50кб. Но это зависит от насыщености картинки деталями.
        +4
        А ещё можно не накручивать на сайт огромное количество скриптов и стилей которые возможно и не нужны.
          +2

          Жаль, что не все с этого начинают и не все понимают важность этого

          +2
          но на первое место всегда ставят Cloudflare

          А разве есть ещё бесплатные cdn кроме него?

          А ещё у них же есть бесплатные Service Workers, на которых можно вручную поднять свой CDN с преферансом и куртизанками.

          А можно про это поподробнее?
            0
            Service Workers бесплатные за $5/месяц.
            У меня, кстати, за сутки бодания с документацией так и не получилось ничего, кроме простого примера, запустить. Например, тот же KV из примеров вообще не завелся…
            0
            Ничего не было сказано о минификации HTML, JS, CSS и SVG, а это все-таки дополнительная экономия.
              +1
              Статья для новчика. Новичек с ней заедет в засаду, если попытается применить на практике:

              1) Ничего не написано про то, что для работы gzip_static и brotli_static в Nginx вообще-то надо не только включить эти директивы но и еще самостоятельно пережать контент. Директивы всего лишь предписывают серверу использовать заранее сжатый контент, если он есть. А если заранее сжатого контента нет, то директивы сами по себе бесполезны. Так что придется скачать тулзы brotli и zopfli а потом еще написать скрипт, который пройдется по вашему контенту и все посжимает. Если статика время от времени меняется то скрипт надо будет потом прогонять повторно что бы сжатые версии стали бы актуальными. Для этого надо будет либо сделать какой-то автоматический триггер, либо озаботиться организационными мерами.

              2) Ничего не написано про промежуточные кэши и про заголовки Accept-encoding в запросе и Vary:accept-encoding в ответе. Без этого появляются неиллюзорные шансы выстрелить в себе в ногу при настройке кэширования. Ну то есть утверждение о том, что Brotli работает только по HTTPS, связано как раз с этми самыми промежуточными кэшами. Про Brotli сказано а про Vary нет.

              3) В примере про настройку cache-control в Apache зачем-то написана странная штука:

              <FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
                      Header unset Cache-Control
              </FilesMatch>
              <ifModule mod_expires.c>
                  ExpiresActive On
                  ExpiresDefault "access plus 5 seconds"
              	куча всего
              </ifModule>
              

              В скриптах могут быть какие-то свои настройки кэширования. В этом конфиге заголовки, выданные скриптом, будут тупо сброшены и заменены на заголовок Expires из конфига. Если о скриптах ничего не известно то это так себе конфиг.

              4) Ничего не сказано про необходимость использования версионирования. Например вы кэшируете /index.html на 1 день (потому что там, например, прайс и он меняется раз в день) а стиль /default.css кэшируете на 1 год. Допустим что страницу и стиль кардинально синхронно поменяли. Клиент зайдет через неделю, страница у него будет новая а стиль будет старый, что обычно приводит к ломке верстки. Для предотвращения этой проблемы надо именовать стили, включая в имя файла постоянно возрастающий номер версии. Ну и после этого еще и не забывать пережимать стили после изменения (см. п. 1).

              5) Опять же — минификация картинок, стилей, скриптов и самих страниц. Для текстов — откат с utf-8 на 8-битную кодировку, если это возможно, мы жде тут каждый байт экономим.
                0

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

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое