Автор Тема: Prestashop, Varnish, HTTPS. Заметка  (Прочитано 379 раз)

24 Март 2017, 20:02:03
  • Фрилансер
  • *
  • Сообщений: 158
  • Репутация: +5/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Доброго времени уважаемые.
Хочу поделиться одним из способов настройки высокопроизводительного кэширующего прокси Varnish в связке с Nginx для Prestashop с поддержкой HTTPS.  Конечно, в Prestashop имеется встроенная система кеширования, но мне ЗАХОТЕЛОСЬ поднять серверный кэш страниц именно на Varnish.
Проблема в том, что Varnish, в силу понятных причин,  не поддерживает HTTPS кэширование.
Предлагаемый способ позволяет преодолеть данное ограничение.   

«Varnish  - ускоритель веб-приложений, также известный как обратный прокси-сервер HTTP кэширования.»  - цитата из официальной документации.  Желающие без труда смогут найти в сети подробное описание этого продукта.
https://www.varnish-cache.org/docs/4.1/reference/index.html

Коротко, принцип его работы следующий: - сохранять в оперативной памяти HTML код страниц и выдавать его пользователю, не обращаясь к WEB серверу и обработчику PHP. Кэшированием нужно управлять и Varnish осуществляет этот процесс, согласно правилам конфигурационного файла.  HTTPS шифрование делает процесс распознавания кэша невозможным и, поэтому, шифрование   должно производиться Nginx на «выходе в мир», а Backend с PHP и Varnish должны работать только через HTTP.  Но в этом случае, необходимо как минимум, переписывать все HTTP URL  на HTTPS. Кроме того, PHP должно «знать», что обращение идёт по HTTPS….   Существует возможность осуществить изменения URL в Nginx, некоторые любители изящных решений используют LUA.  Процесс творческий, предлагаю   выкладывать свои решения, а я предложу своё.
Итак:
Prestashop 1.6
Реализация PHP:  php-fpm, php 6.0
Сервер:    Nginx -1.11
Varnish5
Предполагается уровень подготовки читателя, не требующий объяснения азов установки и настройки софта в *NIX системах.

Схема решения простая – полный HTTPS и «внутри» и «снаружи».  Но ведь это противоречит поставленной задаче, делает её невыполнимой!  На самом деле, это не так.   Есть в Prestashop полезная опция– служебные IP адреса (Настройки\Обслуживание).  Как известно, Prestashop позволяет HTTP соединения с этих адресов, несмотря на то, что весь остальной трафик идёт только через HTTPS.  Нужно добавить 127.0.0.1 в список служебных адресов.

 Принципиальная схема решения:

              __________________NGINX____________________           
             |                                                                                 |
              HTTPS BACKEND                               HTTPS FRONTEND                <==HTTPS==> INET
              127.0.0.1:8080                             proxy_pass http://127.0.0.1:80   
             |_____________|                               |_____________|
                                       |_____<==>_____ |   
                                      VARNISH  HTTP                 
                             


Таким образом,  Varnish получает\обрабатывает запросы по HTTP с сохранением схемы HTTPS. 
Varnish кеширует сгенерированные Бэкендом страницы, объём кеша - 256 Мб
Статика берётся Фронтэндом с диска, минуя Бэкенд и кешируется на стороне клиента.
Cookies проксируются Varnish «насквозь», не кэшируются.
HTML траффик зарегистрированных пользователей не кэшируется.

В заметке просто обсуждается идея HTTPS+VARNISH. А сложные схемы кэширования – отдельная, большая тема.

Настройка:
NGINX  установлен с опциями:
   DSO=on: Enable dynamic modules support
     FILE_AIO=on: Enable file aio
     HTTP=on: Enable HTTP module
     HTTP_ADDITION=on: Enable http_addition module
     HTTP_AUTH_REQ=on: Enable http_auth_request module
     HTTP_CACHE=on: Enable http_cache module
     HTTP_DAV=on: Enable http_webdav module
     HTTP_FLV=on: Enable http_flv module
     HTTP_GZIP_STATIC=on: Enable http_gzip_static module
     HTTP_GUNZIP_FILTER=on: Enable http_gunzip_filter module
     HTTP_MP4=on: Enable http_mp4 module
     HTTP_PERL=on: Enable http_perl module
     HTTP_RANDOM_INDEX=on: Enable http_random_index module
     HTTP_REALIP=on: Enable http_realip module
     HTTP_REWRITE=on: Enable http_rewrite module
     HTTP_SECURE_LINK=on: Enable http_secure_link module
     HTTP_SLICE=on: Enable http_slice module
     HTTP_SSL=on: Enable http_ssl module
     HTTP_STATUS=on: Enable http_stub_status module
     HTTP_SUB=on: Enable http_sub module
     MAIL=on: Enable IMAP4/POP3/SMTP proxy module
     MAIL_SSL=on: Enable mail_ssl module
     HTTPV2=on: Enable HTTP/2 protocol support (SSL req.)
     STREAM=on: Enable stream module
     STREAM_SSL=on: Enable stream_ssl module (SSL req.)
     STREAM_SSL_PREREAD=on: Enable stream_ssl_preread module (SSL req.)
     THREADS=on: Enable threads support
     WWW=on: Enable html sample files
      LUA=on: 3rd party lua module

Схема конфига Nginx. Почему не весь конфиг? ….. весь выкладывать нельзя.
Для понимания идеи заметки – более чем достаточно. 
Опции расписывать не буду – кому нужно, смотрите справочник.
http://nginx.org/ru/docs

nginx.conf
user  польз-ль, от имени которого работает сервис;
worker_processes  auto;
worker_rlimit_nofile 40000;
error_log  ./error.log;
pid        ./nginx.pid;

events {
    worker_connections 1024;
    multi_accept on;

       }
http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 access_log   ./access.log main;
 server_tokens off;

#HTTP to HTTPS – слушаем 80-й порт и перенаправляем на 443 HTTPS

server {
        listen X.X.X.X:80;
        server_name mydomain.com;
        rewrite ^(.*) https://$server_name$1 permanent;
        }

# HTTPS Frontend
server {
        server_name  mydomain.com;
        listen  x.x.x.x.:443 ssl ;
        access_log  ./access2.log main;
 
#SSL параметры A+       
         ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_certificate ./cert.pem;
        ssl_certificate_key   ./key.pem;
        ssl_stapling on;
        ssl_dhparam ./dhparam.pem;
        ssl_ciphers kEECDH+AES128:kEECDH:kEDH:-3DES:kRSA+AES128:kEDH+3DES:DES-CBC3-SHA:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv2;
        add_header Content-Security-Policy-Report-Only "default-src https:; script-src https: 'unsafe-eval' 'unsafe-inline'; style-src https: 'unsafe-inline'; img-src https: data:; font-src https:
# Strict-Transport-Security
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

#Компрессия
        gzip  on;
        gzip_min_length 1024;
        gzip_buffers 40 8k;
        gzip_comp_level 6;
        gzip_types  text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
        gzip_disable "msie6";
        gzip_proxied expired no-cache no-store private auth;

####################Опции проксирования VARNISH #####################################
        location / {
                proxy_pass             http://127.0.0.1:80;      # Запросы к VARNISH
                proxy_set_header       Host $host;
                proxy_set_header    X-Real-IP         $remote_addr;
                proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
                proxy_set_header    X-Forwarded-Proto https;
                proxy_set_header    X-Forwarded-Port 443;
                proxy_set_header    X-Forwarded-Ssl on;

                   }
      # Статические данные
 location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|woff|woff2|ttf|zip)$ {
                root Корень сайта;
                proxy_ignore_headers Cache-Control Expires;
                add_header Cache-Control public;
                expires max;
                access_log off;
                }
    }


# BackEnd
server {
        listen 127.0.0.1:8080;   # Канал от VARNISH
       listen х.х.х.х.:443 ssl;

        server_name  mydomain.com;
        root  Корень сайта;
        index index.php index.html index.htm;

# Достаточно сертификата и ключа
        ssl_certificate ./cert.pem;
        ssl_certificate_key   ./key.pem;

# Ниже локэйшены бэкенда
…..
}

Пример дл. Престашоп - можно использовать, как бэкенд
https://gist.github.com/julienbourdeau/79961e9caa4263e9e34d2d056948d335


VARNISH 5 – устанавливается без опций.
Пользователь varnish должен быть членом той же группы, что и Nginx
Пермиссии:
Каталог с конфигом пользователь varnish - чтение\запись\ выполнение
Файл конфига - для п-теля varnish  только чтение

Рабочий пример конфига:
https://github.com/CleverCloud/varnish-examples/blob/master/prestashop.vcl
Свой не привожу, поскольку использую его как дополнительный фаервол.

Проверка конфига

 varnishd -C -f путь/default.vcl

Перезапуск конфига, без рестарта, с сохранением кеша
varnishd reload

Параметры запуска: Адрес – петля, объём кэша 256М и путь до конфига
varnishd_flags="-a 127.0.0.1:80  -s malloc,256m -f путь/default.vcl"

Статистика
varnishstat
varnishstat -1

Консоль управления

varnishadm


Контроль работы кэша:
1. varnishstat
2. HTTP заголовки
  X-Varnish-Cache HIT
  Age - возраст кэша страницы. Если не ноль - выдано из кэша.

Имейте в виду, что первая проверка покажет отсутствие кэша, страницы должны сначала закэшироваться.
-----------------------------------------

Документация по varnish:
https://www.varnish-cache.org/docs/4.1/reference/index.html


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

05 Апрель 2017, 12:19:53
Ответ #1
  • Модератор
  • Ветеран
  • *****
  • Сообщений: 22307
  • Репутация: +17114/-1
  • Разработка веб-сайтов и веб-программирование
    • Просмотр профиля
Цитировать
Ничего нового, наверняка подобные решения уже не раз обсуждались где-то. Но надеюсь, заметка будет кому-то полезной.
Может и обсуждалось, но так подробно и в одном месте не встречал.
Класс, спасибо.
Интернет-магазин под ключ.
Какой выбрать движок для интернет магазина ?
Какой движок лучше ?
Magento или Prestashop ?
Решение всех Ваших вопросов в создании Интернет-магазина.
06 Апрель 2017, 10:25:03
Ответ #2
  • Ветеран
  • *****
  • Сообщений: 2991
  • Репутация: +72/-5
  • Сообщество PrestaShop
    • Просмотр профиля
14 Апрель 2017, 09:23:39
Ответ #3
  • Фрилансер
  • *
  • Сообщений: 158
  • Репутация: +5/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Похоже, тема интересна. Спасибо за плюсы.

В качестве бонуса хочу предложить shell скрипт обновления кэша Varnish.

Скрипт создает список URL  сайта, обращается к каждому адресу ч-з Curl. Сгенерённые таким образом страницы сохраняет Varnish.
Используется прокси. Прокси нужно вносить  самостоятельно.   Проверку и выбор прокси писать не стал. Проще внести одну строку в скрипт.

Скидовые прокси
https://hidemy.name/ru/proxy-list/?ports=3128&type=s#list

#!/bin/sh    # На bash не проверял, но должно работать.
 
root_dir='корень сайта'

# .xml файлы карты сайта.  Кроме index_sitemap.xml Путь учитывается.  Если файл один, ошибки не будет.
 
maps="$root_dir/1_en_0_sitemap.xml $root_dir/1_es_0_sitemap.xml $root_dir/1_ru_0_sitemap.xml"

#  прокси : порт
proxy=77.73.66.136:3128 

url_list=url_list

# Очистка файла с URLs
:> url_list


# Создаётся список URL.

for file in $maps;
        do
                cat $file | grep "<[/]*loc>" | sed 's/[<][/]*loc[>]//g;s/^[ \t]*//' | sed "s/.*/&/" | tr -d '\r'  >> $url_list

        done

# Проход Curl-ом по списку адресов

if [ -s $url_list ]; then
        target_url=`cat $url_list`
                for url in $target_url
                        do
                               
                                curl -K curl_config  -k --proxy $proxy $url
                        done
                                else
                                        echo "$url_list  не существует или пуст"
fi

exit 0


файл curl_config:
-H "Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8""
-H "Accept-Encoding: "gzip, deflate, br""
-H "Accept-Language: "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3""
-H "Connection: "keep-alive""
-H "Cache-Control: "max-age=0""
-m 6
-o /dev/null

Вывод скрипта :
                                 Dload  Upload   Total   Spent    Left  Speed
100 78113  100 78113    0     0  60167      0  0:00:01  0:00:01 --:--:-- 60179
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 78113  100 78113    0     0  61140      0  0:00:01  0:00:01 --:--:-- 61169
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 78113  100 78113    0     0  60842      0  0:00:01  0:00:01 --:--:-- 60835
.........


Побочный эффект использования - скачёк посещений на графике статистики. (если статистика не удалена)

С эмуляцией смотрелок курлом (Агентами)   заморачиваться не стал, чтоб получить явную разницу с "живыми" обращениями в логах.  Если acess.log отслеживаете, нет проблем вычленить agent Curl

Строки вида
"GET / HTTP/1.1" 301 178 "-" "curl/***" "-"
14 Апрель 2017, 10:30:58
Ответ #4
  • Ветеран
  • *****
  • Сообщений: 2991
  • Репутация: +72/-5
  • Сообщество PrestaShop
    • Просмотр профиля
А ты реальные замеры делал? Интересно сравнить. Скорость работы насколько лучше? А то часто читаю, что varnish нужен при множестве статики. Думал что для престы бесполезен.
14 Апрель 2017, 13:49:28
Ответ #5
  • Фрилансер
  • *
  • Сообщений: 158
  • Репутация: +5/-0
  • Сообщество PrestaShop
    • Просмотр профиля
Миколас

А что имеется в виду под замерами?

Например, ответ сервера на Яндексе, https://webmaster.yandex.ru/tools/server-response/  возврат главной страницы
Первый ответ  (без кэша Varnish) грубо 2,2 секунды, повторная проверка (из кэша Varnish) - 134 мс.

webpagetest.org - из кэша V-sh:
index.php На диаграмме 329 мс, в Details:  Time to First Byte: 236 ms , Content Download: 3 ms...

-------------------------------------

По поводу статики -  Varnish кэширует HTML код, возвращаемый php. Статика берётся фронтэндом Nginx прямо с винта, минуя бэкэнд.
Может мы просто не понимаем друг друга, что имеешь в виду под статикой?

Кэш всегда рациональнее это ясно. Хотя бы для разгрузки сервера и устойчивости.  Ну а скорость загрузки и скорость возврата HTML кода это не совсем одно и тоже.


14 Апрель 2017, 15:38:18
Ответ #6
  • Ветеран
  • *****
  • Сообщений: 2991
  • Репутация: +72/-5
  • Сообщество PrestaShop
    • Просмотр профиля
Цитировать
(без кэша Varnish) грубо 2,2 секунды, повторная проверка (из кэша Varnish) - 134 мс.
Вот это и имел в виду.  С цифрами сразу ясно. Спс.