• «Strangler Application» и SSI

    When Cindy and I went to Australia, we spent some time in the rain forests on the Queensland coast. One of the natural wonders of this area are the huge strangler vines. They seed in the upper branches of a fig tree and gradually work their way down the tree until they root in the soil. Over many years they grow into fantastic and beautiful shapes, meanwhile strangling and killing the tree that was their host.

    Martin Fowler, «Strangler application»

    strangler vines

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

    Переписать всю эту логику, сохраняя работоспособность системы во всех граничных случаях не представлялось возможным, как и развитие имеющейся системы. Было принято решение использовать принцип «Strangler Application», постепенно реализуя отдельные компоненты с нуля и заменяя ими старые. Но, к сожалению, цена входа оказалась слишком велика. Не было проблемой переписать серверную логику, формирующую отдельный блок, но чтобы интегрировать получившийся код на страницу, также требовалось бы переписать серверную логику и всех остальных блоков на странице, т.к. при инициализации приложение серьёзно затрудняло возможность аккуратного подключения каких-то сторонних компонентов. Но вместо того чтобы кушать слона целиком, слона следует кушать понемногу :)

    В такой ситуации может оказаться полезной такая технология, как SSI. Она позволяет осуществлять пост-процессинг тела ответа, например, применять условные функции или делать дополнительные запросы. При реализации «Strangler Application» это может пригодиться следующим образом: старое приложение загружается как обычно, но вместо какого-то отдельного блока на странице происходит обращение к новому приложению. Веб-сервер, получив такие инструкции, делает дополнительный запрос по указанному адресу и вместо инструкции SSI размещает полученный ответ. Можно сравнить это с загрузкой блока посредством AJAX-запроса, но только значительно быстрее и совершенно прозрачно для пользователя, т.к. вся магия происходит еще на сервере, до отправки ответа клиенту.

    Такая строка в коде сайта заставит сервер сделать запрос по адресу «/my-new-application-url» и «вклеить» его результат в код сайта:

    <!--# include virtual="/my-new-application-url" -->

    В конфиге nginx следует разрешить такие запросы:

    location / {
      ...
      ssi on;
      ...
    }

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

    Следует также учесть, что обработка инструкций SSI происходит только в том случае, если nginx получает ответ от апстрима в чистом виде, без сжатия. Если ответ будет сжат, инструкции выполнены не будут.

One is the pinnacle of evolution; another one is me

One on the picture is the pinnacle of evolution; another one is me: inspired developer, geek culture lover, sport and coffee addict