Современные потребности в области управления контентом
Еще 10-15 лет назад большинство компаний для взаимодействия со своими клиентами в цифровом сегменте ограничивались преимущественно сайтами. Однако, в последнее десятилетие ситуация существенно изменилась на фоне бурного технологического роста на рынках мобильных устройств и телекоммуникаций: большинство из нас уже не могут представить свою жизнь без современного смартфона со скоростным доступом в Интернет из практически любой точки мира.
Поэтому сегодня как крупный, так и малый бизнес, ориентированный на продажу своего продукта или услуги массовому потребителю, активно идет (и многие уже пришли) в сторону расширения своего присутствия на цифровых платформах. Это важный процесс, и с точки зрения задачи сохранения существующей аудитории, и для привлечения новых клиентов. Компании создают сайты с адаптивной версткой, мобильные приложения для iOS и Android, чат-боты в Telegram, мини-приложения в Vk, приложения для SmartTV и пр.
Каждое решение на этих платформах нуждается в контенте для привлечения внимания пользователя и последующей конвертации этого внимания в продажу. Так что же такое контент, из чего он состоит?
Контент (от англ. content – содержание, содержимое) – это информация, представленная в текстовом, графическом или аудио формате, и размещенная на некотором ресурсе.
Это определение можно детализировать тремя дополнительными понятиями:
Форма подачи контента – способ организации информации. Новости, статьи, фотоколлажи, видеоролики, музыкальные композиции, инфографика, карточки продуктов и услуг – это лишь малый список различных форм подачи контента.
Форма подачи никак не зависит от конечной платформы, на которой будет размещен контент. Новость, опубликованная на сайте, по форме и смысловому содержанию останется той же новостью при ее публикации и в мобильном приложении, и в Telegram, и где-либо еще.Модель данных контента – логическая структура сущностей, из которых состоит контент. Объекты этих сущностей могут быть выражены в виде текстовой информации, изображений, видео или аудио.
Логические связи сущностей и используемые типы данных так же остаются неизменными при публикации контента на различных платформах.Представление контента – способ визуализации объектов модели данных, в более привычном смысле это верстка.
Технологии верстки для различных платформ (веб / мобильные приложения / Telegram и т.д.) существенно отличаются. Использовать HTML-разметку, применяемую на сайте, для верстки экрана в мобильном приложении не получится. Кроме того каждая из платформ имеет уникальные особенности стилизации пользовательских интерфейсов, гайдлайны, требования к объему информации и прочие факторы, которые должны влиять на окончательный внешний вид представлений с контентом. И это основная проблема, которую требуется разрешить, при публикации одного и того же по смыслу контента на различных ресурсах.
Сегодня ключевой потребностью компаний становится централизованный инструмент, с помощью которого можно было бы управлять контентом сразу на всех платформах присутствия. Среди основных преимуществ наличия такого решения можно выделить следующие:
оптимизация штата сотрудников, непосредственно задействованного в процессе управления контентом: контент-менеджеры / дизайнеры / маркетологи и др.
минимизация рисков человеческого фактора за счет отсутствия необходимости готовить несколько версий одного и того же контента для публикации на разных платформах;
сокращение показателя time-to-market: подготовить, согласовать и опубликовать один материал сразу для всех платформ значительно быстрее, чем сделать все то же самое для каждой.
Наш опыт решения задачи
Дисклеймер
Правила Хабра запрещают любую рекламу компаний и их проектов вне корпоративных блогов. Поэтому описание проекта в данной статье сознательно не будет конкретизировано. Любые совпадения случайны.
Краткое описание проекта
Проект, для которого мы решали задачу мультиплатформенного управления контентом, ориентирован на продажу продуктов компании массовому потребителю. В цифровом сегменте проект представлен в виде сайта, нативных приложений на iOS и Android и Telegram-бота. Также у бизнеса есть долгосрочные планы по дальнейшей экспансии на другие платформы.
Аудитория проекта на всех платформах за последний год в уникальных посетителях:
в среднем: ± 300 000 / сутки;
в пике: ± 1 250 000 / сутки.
С точки зрения разнообразия и объема контента:
часто изменяемый контент: около 20 разных типов в среднем до 50 актуальных элементов в каждом (карточки и страницы продуктов, баннеры, stories и пр.);
медиа контент: в среднем по 5-6 новых материалов в неделю (новости, статьи, интервью и пр.);
относительно статичный контент: порядка 30 различных страниц (информация о компании, контакты, партнерские программы и пр.).
Исторически для управления контентом использовалось три (!) решения собственной разработки. Представленная в решениях функциональность выглядела достаточно скудно, и при этом граница ответственности сервисов была сильно размыта. Т.е. часть контента для мобильных приложений управлялась из одного инструмента, а другая часть из второго. Так же для публикации условного баннера и в мобильных приложениях и на сайте необходимо было создать соответствующие объекты в нескольких инструментах. При этом бизнес-потребность по суммарному объему новых публикаций или изменениям в существующих составляла несколько десятков в неделю.
Перед нами была поставлена следующая задача:
Бесшовно и незаметно для пользователей внедрить единый инструмент для управления контентом на всех цифровых платформах взамен существующего исторического наследия из нескольких самописных сервисов.
Способы решения задачи
Рассмотрим основные способы решения задачи, их преимущества и недостатки:
1. Создание собственного продукта
Преимущества:
полный контроль над используемым технологическим стеком и процессом разработки;
возможность реализации любой уникальной и нетипичной функциональности для решения проектных задач;
только востребованная функциональность в конечном продукте, т.е. он будет легче и производительнее (конечно, при условии, что его разработкой занимались компетентные специалисты на протяжении достаточного периода времени).
Недостатки:
долго: создание качественных продуктов «с нуля» измеряется человеко-годами;
дорого: во-первых потому что долго, во-вторых потому что требуется штат высококвалифицированных и опытных специалистов.
Для подавляющего большинства компаний создание собственных продуктов для управления контентом экономически нецелесообразно. По моему субъективному мнению такой подход может быть рациональным для компаний, основная деятельность которых заключается в создании и предоставлении контента пользователям, при условии наличия уникальных требований к функциональности (СМИ, тематические форумы, коллективные блоги и т.п.).
2. Использование коробочной CMS
Преимущества:
большой выбор продуктов на рынке как среди open-source, так и коммерческих решений, специализирующихся на решении всевозможных типовых задач;
доступность базовой функциональности из коробки;
широкий выбор плагинов и подключаемых модулей для расширения возможностей продукта, например, для интеграций с другими распространенными решениями;
наличие специалистов с опытом работы с популярными решениями для конфигурирования и кастомизации продукта под конкретные требования проекта;
актуальная и достоверная документация.
Недостатки:
относительно низкая производительность как плата за универсальность;
избыточная (невостребованная) для конкретного проекта функциональность;
бОльшая уязвимость: чем популярнее продукт, тем больше направленных на него атак от злоумышленников.
Преимущества использования коробочного продукта для решения типовых задач достаточно очевидны. Это и быстрее, и дешевле, и в большинстве случаев закрывает все актуальные потребности проекта. В целом такой подход является общепринятой практикой: так, например, мало у кого возникает идея создать собственную Система управления базами данных</p>" data-abbr="СУБД">СУБД или брокер сообщений. Безусловно, такие проекты есть, и некоторая их часть впоследствии получает мировое признание (Redis, Kafka и пр.), но по большей части они со временем отправляются на кладбище «изобретенных велосипедов».
Учитывая вполне типовые требования нашей задачи мы остановились на коробочной CMS. И столкнулись с необходимостью определиться с типом CMS, которую мы будем использовать.
Традиционная или Headless CMS?
Решения класса «Headless CMS» представляют из себя приложения из трех основных компонентов:
административная панель с UI для управления контентом;
backend с API над хранилищем контента;
хранилище контента (СУБД и файловое хранилище).
Основное отличие «обезглавленных» CMS от «традиционных» заключается в отсутствии функциональности управления шаблонами представлений. Т.е. API Headless CMS предоставляет только объекты модели данных контента без информации об их представлении (разметки). Соответственно зона ответственности за визуализацию этих объектов остается на стороне клиентских приложений.
И это именно то, что нам нужно в условиях мультиплатформенности. Отлично, осталось выбрать конкретный продукт.
Критерии выбора Headless CMS
Как подойти к выбору инструмента? На первом этапе мы приступили к поиску существующих на рынке решений (хороший список есть на этом ресурсе) и их первичной фильтрации.
В списке базовых критериев оказались следующие:
Тип лицензии: open-source
Способ установки: on-premise
В рамках решаемой нами задачи было важно получить полный контроль над данными, политиками информационной безопасности, ИТ-инфраструктурой и иметь гипотетическую возможность кастомизации продукта под потребности бизнеса.Зрелость продукта
Весьма субъективный параметр. Среди рассматриваемых показателей были в том числе такие: количество форков и звезд у проекта на GitHub, количество решенных вопросов на StackOverflow, частота выпуска версий и объемы изменений, актуальность и достаточность документации и др.
Для более детального рассмотрения были отобраны 4 продукта: Directus, Strapi, Ghost и KeyStoneJS. Сравнительная таблица с результатами анализа ниже (по состоянию на август 2022).
Таблица сравнения Headless CMS
Общие технические критерии | Directus | Strapi | Ghost | KeystoneJS |
Языки и framework-и | Frontend: Vue.js | Frontend: React.js | Frontend: Express.js, Ember.js | Frontend: Next.js on React.js |
Поддерживаемые СУБД | Any SQL-Database, в том числе: | PostgreSQL | MySQL | PostgreSQL |
Поддерживаемые файловые хранилища | S3 | S3 | S3 | Только локальное хранилище на диске |
Поддержка Single-Sign-On и способы аутентификации | OpenID Connect | Только в Enterprise‑версии с GOLD‑подпиской | Нет | Нет |
Реализуемые типы программных интерфейсов | RESTful API | RESTful API | RESTful API | GraphQL API |
Возможности моделирования | Directus | Strapi | Ghost | KeystoneJS |
UI редактор для управления моделями | Да, гибкий редактор с больишм набором элементов из коробки | Да, гибкий редактор с больишм набором элементов из коробки | Нет, предусмотрено несколько типов моделей из коробки | Нет, модели контента определяются JSON Schema без возможности редактирования в UI |
API для управления моделями | Да | Нет, управление моделями только через UI | Нет | Нет |
Миграция моделей между средами | Да, через встроенный инструмент CLI можно создавать и восстанавливать snapshot-ы моделей | Да | Нет | Нет |
Возможности управления контентом | Directus | Strapi | Ghost | KeystoneJS |
UI редактор для управления контентом | Да | Да | Да | Да |
Версионирование контента | Да, есть механизм управления ревизиями | Нет | Нет | Нет |
WYSIWYG-редактор | Да, markdown и HTML | Да, markdown | Да, markdown | Да, markdown |
Возможности административной панели | Directus | Strapi | Ghost | KeystoneJS |
Role-based access control | Да | Да, до 3-х ролей в бесплатной версии | Да, предусмотрено 5 ролей | Нет |
Стилизация админки | Да | Нет | Нет | Нет |
Поддержка русского языка | Да | Нет | Нет | Нет |
Свой финальный выбор мы остановили на Directus, как на наиболее подходящем под наши критерии решении.
Что такое Directus?
Согласно официальной документации Directus позиционирует себя как Платформа открытых данных</p>" data-abbr="Open Data Platform">Open Data Platform, которая может выступать в качестве решений Headless CMS, Системы управления обучением, Системы управления запасами, No-Code платформы для управления данными и других data-driven проектов.
Backend реализован на платформе NodeJS и представляет из себя следующий набор слоев (снизу вверх):
На самом нижнем слое находятся адаптеры к реляционным базам данных и файловым хранилищам. Directus способен работать с любой уже существующей или новой SQL базой данных. При этом Directus не вмешивается непосредственно в структуру «полезных» данных и создает свои таблицы, необходимые для работы API и Data Studio, рядом. Таким образом данные остаются «чистыми», и это одно из ключевых преимуществ.
На следующем уровне разместился Data Engine, который реализует логику доступа к данным. Взаимодействие с базами данных осуществляется с помощью нативного SQL. Движок запросов поддерживает множество DML и DDL-операций.
На ступеньке выше располагаются механизмы кэширования данных и файлов. С версии 10.4.0 прекращена поддержка инструмента Memcached. Разработчики продукта сконцентрировались на более глубокой интеграции с Redis.
Предпоследним является слой аутентификации и авторизации. Directus поддерживает протоколы OAuth 2.0, OpenID и LDAP для реализации технологии Single-Sign-On</p>" data-abbr="SSO">SSO. Также возможно создание и управление локальными пользователями для доступа в Data Studio и статичными токенами для доступа по API. В продукте реализован подход Role-based Access Control для гибкого управления полномочиями пользователей и клиентов API.
На самом верху представлены программные интерфейсы взаимодействия с платформой: REST API, GraphQL, JavaScript SDK и интерфейс доступа через командную строку. Предоставляемые функциональные возможности в REST API и в GraphQL полностью идентичны. Оба интерфейса реализуют технику Database mirroring для динамической генерации методов REST API и GraphQL Schema.
Frontend реализован с помощью фреймворка VueJS и называется Data Studio. По своей сути это UI административной панели для управления:
моделями данных, объектами этих моделей, пользователями и файлами;
ролями пользователей и назначенными им полномочиями;
потоками автоматизации процессов обработки данных.
Несколько официальных видео с демонстрацией разделов Data Studio
Модель данных
Коллекции
Отношения
Объекты моделей
К слову о частоте выпуска версий:
мажорные версии выходят примерно 1 раз в год;
минорные – 1 раз в 2 недели
фиксы и небольшие улучшения – по мере потребности.
Для наглядности:
10.4.3 от 11 июля 2023
10.4.2 от 30 июня 2023
10.4.0 от 28 июня 2023
10.3.0 от 13 июня 2023
10.2.1 от 26 мая 2023
10.2.0 от 25 мая 2023
10.1.1 от 16 мая 2023
10.1.0 от 12 мая 2023
Описание решения задачи
Архитектура решения
Directus
Ключевой компонент решения, зона ответственности которого ограничивается Create Read Update Delete</p>" data-abbr="CRUD">CRUD-операциями с контентом. Directus ничего не знает (и не должен знать) ни о клиентских приложениях, которые визуализируют контент, ни о реализованных ими представлениях, ни тем более о пользователях, которые эти приложения используют.
Горизонтальное масштабирование Directus с сохранением корректной работы части функциональности может быть обеспечено только в случае если отдельно взятый экземпляр будет соответствовать концепции stateless, т.е. не будет хранить состояние внутри себя. Именно поэтому в архитектуре решения используются:
Redis в качестве инструмента для механизма кэширования и функциональности по ограничению скорости обращений к API (rate-limiting);
Все пользователи Directus – внутренние сотрудники, поэтому для обеспечения их доступа в административную панель сконфигурировано взаимодействие с корпоративной службой каталогов Active Directory. В AD настроены группы безопасности в соответствии с используемой ролевой моделью в Directus. Маппинг групп на роли осуществляется внутренним механизмом Directus по совпадению имен.
Для рассылки внутренних уведомлений пользователям настроено подключение к корпоративному почтовому серверу.
cms-proxy-service
Это backend-сервис, который выступает в качестве прослойки между клиентскими приложениями и Directus. Зачем он нужен?
Первая проблема заключается в необходимости создания дополнительного слоя абстракции над REST API Directus. По требованиям задачи нам необходимо было заменить несколько существующих CMS на новую. При этом у клиентских приложений уже был некоторый набор контрактов, которые использовались для работы с контентом из существующих CMS. Прямая замена этих сервисов на новый неизбежно привела бы к изменению этих контрактов. Изменение контрактов, в свою очередь, потребовало бы доработки всех клиентских приложений. Выглядит долго и дорого. Поэтому мы пошли по пути создания прокси-сервиса с REST API, спецификация методов которого по возможности повторяла бы существующие контракты.
Вторая проблема заключается в необходимости ограничить сетевой доступ к Directus из Интернета. Прямое взаимодействие между клиентскими приложениями и REST API Directus привело бы к необходимости публикации интерфейса взаимодействия на входящем балансировщике нагрузки. Т.к. мы не контролируем кодовую базу Directus и не очень хотим этим заниматься, то мы не можем гарантировать отсутствие в нем уязвимостей с точки зрения информационной безопасности. Прокси-сервис решает эту проблему.
Зоной ответственности прокси-сервиса является:
проксирование запросов и ответов между клиентскими приложениями и Directus с необходимыми преобразованиями форматов;
кэширование запросов и ответов на уровне взаимодействия прокси-сервиса с клиентскими приложениями;
применение фильтров по умолчанию.
Perfomance-тесты
Основной целью проведения нагрузочного тестирования являлось определение оптимальной конфигурации решения для обеспечения его стабильной работоспособности в условиях, приближенных к реальной эксплуатации. Второстепенной – оценка производительности Directus при его использовании без прослойки в виде прокси-сервиса.
Все виды тестов проводились на Directus версии 9.23.0.
Предварительно были подготовлены данные в Directus и сформированы запросы к REST API Directus и к REST API cms-proxy-service:
данные в Directus: по 50-100 объектов для каждой из трех самых объемных моделей контента (баннеры / истории / наборы карточек продуктов);
запросы: по 4 запроса на получение списка элементов с разными условиями фильтрации по каждому из трех типов контента, которые возвращали от 10 до 30 элементов.
Профиль нагрузки распределили примерно поровну между всеми 12 запросами.
К сожалению, сохранилось очень мало скриншотов c результатами тестирования, а с динамикой загрузки CPU и использованию RAM не осталось вовсе.
REST API Directus
В ходе тестирования нам удалось получить уверенные 30 RPS на 1 экземпляр при минимальных ресурсах CPU и RAM. При этом наши попытки кратно увеличить количество ядер и объем памяти давали совсем не кратное увеличение производительности. Так, например, один экземпляр с ресурсами в 2 CPU и 4 Гб RAM способен обработать примерно в полтора раза меньше запросов, чем два экземпляра по 1 CPU и 512 Мб RAM.
Результаты тестов Directus
Directus: POD - 2, CPU - 1, RAM - 512 Мб
Кэширование: Directus - TTL 5 мин
Результат: отказ в работоспособности после подачи нагрузки свыше 60 RPS
Directus: POD - 8, CPU - 1, RAM - 512 Мб
Кэширование: Directus - TTL 5 мин
Результат: отказ в работоспособности после подачи нагрузки свыше 250 RPS
REST API cms-proxy-service
Стресс-тестирование на определение пиковой производительности при конфигурации 1 экземпляра с 2 CPU, 2 Гб RAM и внутренним кэшем сервиса с TTL в 30 секунд показали способность этого приложения выдержать до 1 800 RPS. Собственно это не так удивительно, учитывая предельную простоту сервиса.
Результаты тестов cms-proxy-service
Directus: POD - 8, CPU - 1, RAM - 512 Мб
cms-proxy-service: POD - 2, CPU - 2, RAM - 2 Гб
Кэширование: Directus - TTL 5 мин, cms-proxy-service - TTL 30 сек
Результат: тест пройден при подаче до 2 000 RPS на протяжении 20 минут
Directus: POD - 8, CPU - 1, RAM - 512 Мб
cms-proxy-service: POD - 2, CPU - 2, RAM - 2 Гб
Кэширование: Directus - TTL 5 мин, cms-proxy-service - TTL 30 сек
Результат: тест пройден при подаче 1 500 RPS на протяжении 9 часов
В результате тестирования мы остановились на следующих оптимальных параметрах конфигурации, при которых решение уверенно справляется с пиковой нагрузкой в 2 000 RPS и сохраняет свою стабильность при долговременной нагрузке в 1 500 RPS:
Directus: 2 POD, 1 CPU, 512 Мб RAM
cms-proxy-service: 2 POD, 2 CPU, 2 Гб RAM
Это с хорошим запасом покрывает текущие проектные потребности. Если в будущем эта ситуация изменится, то мы без проблем продолжим горизонтальное масштабирование с прогнозируемым увеличением производительности.
P.S.: результатов тестирования без кэширования, честно говоря не помню, показатели были на несколько порядков меньше. Представить ситуацию, в которой контент настолько быстро меняется, что проблема инвалидации кэша становится актуальной, у нас не получилось.
Заключение
Спустя почти год с момента появления идеи о внедрении Directus и до текущего момента мы ни разу не пожалели о принятом решении. За более чем 6 месяцев промышленной эксплуатации мы не столкнулись ни с одной ситуацией простоя сервиса, вызванной проблемами в Directus. Реализованная в продукте функциональность более чем покрывает потребности бизнеса. На сегодняшний день весь динамически изменяемый контент находится под его управлением, завершается перевод статических страниц.
В результате реализации проекта удалось кратно сократить трудозатраты сотрудников на подготовку и публикацию креативов. И при этом сразу для всех платформ! Теперь у контент-менеджеров есть одна понятная инструкция, дружелюбный пользовательский интерфейс административной панели и больше свободного времени на креативную деятельность. Внедрение Directus позитивно сказалось на работе смежных подразделений: отдела маркетинга и веб-аналитики, т.к. процесс управления контентом в целом стал прозрачнее и ощутимо гибче. Решение не осталось незамеченным и со стороны службы эксплуатации: вторая линия поддержки больше не пытается угадать первоисточник проблемы с отображением контента.
В условиях динамически меняющейся конъюнктуры рынка для успеха digital-направления ключевым фактором является способность оперативно и качественно реагировать на любые изменения. Без соответствующих времени инструментов это было бы крайне затруднительно.
Никита Кургачев
Архитектор, АО "Синхро", @nkurgachev