Рубрики
Uncategorized

Использование Nginx для переноса устаревших систем

tl; dr: Использование Nginx для миграции устаревших систем очень мощно. С помощью хитроумных комбинаций правил перезаписи… Помечено как веб-разработчик, php, devops.

tl;dr: Использование Nginx для миграции устаревших систем очень мощно. Благодаря продуманным комбинациям правил перезаписи и обратных прокси-серверов можно реализовать плавные переходы!

Мы демонстрируем вышесказанное, заменяя CMS CMS Neos, но аналогичные идеи могут быть применены ко многим видам систем.

Для одного из наших клиентов стало очевидно, что он не может реализовать свои потребности с помощью своей предыдущей CMS – и после того, как мы показали CMS Neos, быстро стало ясно, что они получат большую выгоду от ее функциональных возможностей, особенно гибкого моделирования контента, управления перенаправлениями и функций SEO.

Однако у заказчика было довольно много контента в старой CMS, а также специальные функции, такие как корзина покупок и различные виды форм, поэтому мы поняли, что замена всего в большом взрыве будет слишком дорогой.

Для нас основным вопросом было: как мы можем раскрыть потенциал Neos CMS для заказчика очень экономичным способом?

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

Идея решения: Сначала доставьте контент Neos, а затем вернитесь к старой CMS

На [Конференции Осз 2018] ( http://neoscon.io ], я присутствовал на выступлении Себастьяна Хойера и Арне Бланкертса о побеге из ада наследия – где они представили схему использования обратных прокси-серверов Nginx, настроенных умным способом. По сути, идея состоит в том, чтобы сначала запросить новую систему, а когда новая система вернет страницу 404, перехватить ее на уровне Nginx; и вместо этого запросить у старой системы тот же URL-адрес.

Таким образом, мы смогли перестроить шаблон в Neos и выполнить постепенную миграцию: мы взяли страницу, где текущая структура была не такой, как ожидалось, и мы перестроили эту страницу в новой системе.

Давайте немного увеличим требуемую конфигурацию Nginx, которая, по сути, сводится к следующим настройкам:

location / {
    # default for Neos CMS; to redirect all pages which do not exist on disk to index.php
    try_files $uri $uri/ /index.php?$args;
}

# default config - passing PHP calls to PHP-FPM via FastCGI
location ~* \.php$ {
    fastcgi_pass   unix:/tmp/php7-fpm.sock;
    # ... quite some more fastcgi parameters here

    # when PHP delivers an HTTP error, do not send this to the end-user directly,
    # but instead evaluate the error_page directive.    fastcgi_intercept_errors on;     

    # redirect to the named @legacy location in case of a 404 from the new system.    
    error_page 404 = @legacy;     
    # also allow if that happens multiple levels.   
    recursive_error_pages on;
}

# definition for the legacy backend
location @legacy {
    # ... (see below)
}

Теперь у меня возникли некоторые проблемы с правильным определением устаревшего бэкэнда, потому что при моих первых попытках определить proxy_pass URL-адрес/index.php всегда вызывался в устаревшей системе. Затем небольшая отладка и чтение документов показали, что происходит:

  1. Директива try_files работает как некоторое внутреннее перенаправление; эффективно переписывает внутренние переменные Nginx, такие как $uri, в/index.php .
  2. затем выполняется блок определения местоположения PHP – и если PHP вернул ошибку 404, текущий запрос (который все еще был запросом на/index.php) был возвращен в устаревшую систему.
  3. устаревшая система (конечно) не могла обрабатывать запросы на/index.php и вернул сообщение об ошибке.

Итак, возник вопрос: как мы можем использовать исходный URL-адрес (перед началом перезаписи) и передать его в устаревшую систему восходящего потока?

Решение довольно простое, но потребовалось немного времени, чтобы разобраться в этом. Основная идея состояла в том, чтобы использовать переменные внутри proxy_pass для динамического создания целевого URL-адреса:

location @legacy {
    # we use the ORIGINAL request URI (including all arguments) here.
    # To quote the docs at https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass:
    #     When variables are used in proxy_pass the URL
    #     is passed to the server as is, replacing the original request URI.
    proxy_pass https://old.my-url.de$request_uri;

    # we need to define a resolver, as we use variables and a full domain name in proxy_pass
    resolver 8.8.8.8;

    # for the dynamic parts to work, we need to rewrite Location headers to be relative again, because we use a
    # dynamic $request_uri in proxy_pass - and thus the default rewriting of proxy_redirect does not happen anymore.
    proxy_redirect https://old.my-url.de/ /;
    proxy_redirect http://old.my-url.de/ /;
}

В нашей настройке выше динамические страницы обрабатываются php-fpm; и все статические файлы (например, изображения, css, …) доставляются непосредственно из системы nginx, которая также выполняет проксирование. Таким образом, мы хотим избежать запроса нашего нового бэкэнда для каждого статического актива; просто вернуть 404, а затем запросить устаревшую систему (у которой есть актив).

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

location ~* \.(?:css|png|js|woff|woff2|svg|jpg|jpeg|ttf|pdf)$ {
    # if these static files do not exist on disk, directly ask the legacy backend.
    error_page 404 = @legacy;
}

Наконец, для дальнейшего увеличения времени отклика мы добавили простой кэш, который кэширует все устаревшие ресурсы в течение 10 минут, используя приведенные ниже правила:

proxy_cache_path /tmp/nginx-cache levels=1:2 keys_zone=legacy:50m inactive=24h  max_size=1g;

location @legacy {
    #  ... the config from above, and additionally the following lines:

    proxy_cache legacy;
    proxy_cache_background_update on;
    proxy_cache_use_stale  error timeout invalid_header updating
                           http_500 http_502 http_503 http_504;
    proxy_cache_valid 200 302 10m;
}

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

  • Этот подход (для веб-сайтов) можно использовать только в том случае, если старая и новая системы имеют одинаковый визуальный вид; т.е. HTML-разметка может быть использована повторно.
  • Это лучше всего работает для систем, которые хорошо сегментированы; поэтому у нас нет большого количества взаимосвязей между “старой” и “новой” системой. Это намного сложнее, если старой и новой системе требуется доступ к одному и тому же базовому хранилищу данных.
  • Этот подход не содержит встроенного способа доступа к общим данным; т.е. страница всегда отображается исключительно в новой или исключительно в старой системе. Это немного усложняет работу с глобальными данными, такими как поисковый индекс, меню или sitemap.xml (о котором нужно позаботиться по-другому).
  • Этот подход лучше всего подходит для систем с большим объемом чтения.
  • Этот подход позволяет использовать многие мощные функции Neos, такие как управление перенаправлениями, также для контента в старой системе (поскольку перенаправления возвращаются в первую очередь из новой системы).

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

Оригинал: “https://dev.to/skurfuerst/using-nginx-to-migrate-legacy-systems-2ilo”