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

Мы будем использовать React и Next.js, но меньше внимания будем уделять коду и больше функциям ConfigCat. Мы ответим на следующие вопросы:

  • Что такое ConfigCat и зачем его использовать?
  • Как реализовать ConfigCat на стороне клиента?
  • Почему выполнение последнего может быть не тем, что вы хотите?
  • Как внедрить ConfigCat на стороне сервера?

Отказ от ответственности: эта статья не является учебным пособием по ConfigCat. Для этого его разработчики сделали очень достойную документацию с примерами конкретных SDK, включая как серверный, так и клиентский JavaScript. С учетом сказанного давайте углубимся в тему сегодняшнего дня.

Так что же такое ConfigCat?

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

Короче говоря, логика принятия решений переносится из вашего приложения в ConfigCat.

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

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

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

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

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

Что, если бы вы могли избежать этой боли с помощью простого вызова API? Неплохо, но это заставляет вас звонить в стороннюю службу с каждым запросом клиента, что может обойтись дорого. А что, если бы вместо этого мы могли иметь конфигурацию флага функции в нашем собственном кеше и обновлять ее только при необходимости? Это более или менее то, где ConfigCat может пригодиться.

1. Принятие решений

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

2. Кэширование

Наш вызов сначала попадает в локальный кеш, и только если ответ там не найден, он переходит к самому ConfigCat.

3. Конфигурация флага функции

Через некоторое время мы можем захотеть обновить настройку. Допустим, тест прошел успешно, и теперь мы хотим показать подписку 50% клиентов, а не только 10. Здесь в игру вступает функция под названием вебхуки.

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

Все эти детали станут ясны, как только мы увидим код.

Настройка учетной записи ConfigCat и флагов функций

1. Компоненты ConfigCat

Давайте рассмотрим основные компоненты configcat.

настройка — конкретное лицо, принимающее решение. В этой статье мы будем использовать термины

флаг функции и параметр взаимозаменяемы, но на самом деле параметр логического типа называется флагом функции.

config — логический набор настроек.

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

продукт — оболочка над набором конфигураций и сред.

2. Настройка учетной записи

Мы начнем с установки флага нашей функции в веб-интерфейсе ConfigCat. Перейдем на https://app.configcat.com/ и создадим бесплатную учетную запись.

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

После регистрации вы должны получить продукт по умолчанию. Если нет — создайте. Далее создайте конфиг. Просто сохраните имя по умолчанию, которое в моем случае — «Main Config».

Затем в левом верхнем углу содержимого страницы выберите опцию «+ Добавить флаг функции». Как упоминалось ранее, это параметр, который возвращает либо true, либо false. Это идеально подходит для нашего варианта использования, поскольку мы хотим знать только, следует ли показывать флажок конкретному пользователю. Назовите флаг «show_carbon_neutral_checkbox» и оставьте все остальное по умолчанию.

3. Панель управления ConfigCat

Теперь давайте посмотрим на панель управления нашей новой конфигурации.

В верхней части навигации вы увидите имя вашей среды в качестве последнего элемента. Скорее всего, это будет либо «Prod», либо «Dev».

Config cat по умолчанию подготовил для нас два окружения. Просто оставим их как есть. В вашем собственном приложении вы можете переименовать их или добавить еще пару для своих сцен. Однако имейте в виду, что бесплатный уровень configcat в настоящее время поддерживает только две среды.

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

Обратите внимание на кнопку в правом верхнем углу с надписью «Просмотреть ключ SDK». Ключ SDK — это ключ API для доступа к ConfigCat. Он уникален для комбинации config и среды. Наше приложение будет использовать ключ SDK для доступа к конкретному экземпляру конфигурации ConfigCat. Не перепутайте промежуточные и рабочие ключи SDK, когда работаете над реальной функцией.

4. Логика принятия решений ConfigCat

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

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

Для нас это означает, что configcat ожидает, что пользовательский объект будет включен в запрос. ConfigCat предлагает три поля для такого объекта — идентификатор, страна и адрес электронной почты — но все они являются необязательными. Вы также можете включить вложенный объект под названием «Пользовательский» и поместить туда любые свойства, которые имеют отношение к принятию решений в вашем случае использования.

Идентифицированный пользователь — это любой пользователь, который имеет некоторую информацию в своем пользовательском объекте, отправленном в configcat — будь то идентификатор, страна, адрес электронной почты или какое-либо пользовательское поле, предоставленное нами.

Вызов ConfigCat из внешнего кода

Теперь перейдем к нашему проекту. Это внешнее приложение React, созданное с помощью create-react-app, из которого я удалил все, что не требуется для этой демонстрации.

Нам нужно установить ConfigCat как зависимость с помощью:

npm i configcat-js

Мы будем держать вещи ужасно простыми. Вы не отправите такую ​​веб-форму клиенту, но для нашего демо она сойдет. Вот код компонента:

1. Создайте клиента

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

Метод, который создает клиент, принимает ключ SDK, который мы видели ранее.

2. Позвоните в ConfigCat для принятия решения

При каждом рендере компонента мы делаем вызов ConfigCat. Мы включаем пользовательский объект в наш запрос. Этот объект имеет только идентификатор, привязанный к определенной вкладке браузера. При первой загрузке страницы во вкладке браузера значение флага функции (не конфигурация) сохраняется в локальном хранилище с TTL, равным 60 секундам. Флажок либо есть, либо нет, в зависимости от того, насколько нам повезло попасть в 50% целевую группу нашего эксперимента. Как бы часто вы ни обновляли эту единственную вкладку — по крайней мере, в течение 60 секунд ничего не меняется. Если вы переключаетесь на другую вкладку — вы, по сути, снова подбрасываете монету.

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

Наконец, мы создаем входной тег для флажка платы за окружающую среду и показываем его только в том случае, если configcat говорит, что он включен для текущего пользователя.

Почему ConfigCat во фронтенде — не лучшая идея

Теперь, когда мы успешно реализовали флаг, давайте поговорим о главном недостатке его реализации во фронтенде — отсутствии должного кеширования. По сути, мы будем выполнять вызов configcat каждый раз, когда новый пользователь обращается к нашей странице, не говоря уже о перезагрузке кеша или возможном устаревшем кеше.

Как клиент configcat у вас есть определенная квота вызовов API. Выход за рамки этого может очень быстро стать дорогим. Вы можете увидеть свое текущее использование, перейдя на веб-сайт configcat и выбрав «Использование и квота» в меню продукта.

Вот почему лучшим решением будет вызвать ConfigCat из нашего внутреннего интерфейса и позволить внешнему интерфейсу отображать страницу на основе того, что он получает с сервера, и ничего больше.

Вызов ConfigCat из серверной части

Давайте посмотрим на другой пример, где наша страница создана на стороне сервера и отправлена ​​клиенту.

Но сначала давайте изменим логику конфигурации нашего флага функции, чтобы она была немного более сложной. Теперь вместо того, чтобы просто подбрасывать монетку, мы хотели бы знать, исходит ли запрос пользователя с мобильного устройства. Для этого нам понадобится раздел custom пользовательского объекта — туда мы можем поместить все, что угодно. Давайте придумаем простой логический параметр под названием isMobile.

1. Позаботьтесь о кэшировании

Взгляните на следующий файл, в котором мы определяем кеш для нашего клиента ConfigCat. По умолчанию он будет использовать кеш в памяти. В реальном приложении вы бы использовали более сложное решение, такое как Redis. Здесь мы просто используем файл json в файловой системе нашего сервера.

2. Создайте клиента

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

Наше серверное приложение очень простое, даже если вы не знакомы с Next.js. У нас есть компонент React и метод getServerSideProps. Этот метод работает на сервере. Он принимает запрос пользователя и обрабатывает связь с ConfigCat. Затем он передает полученное значение флага функции компоненту React, который теперь является чистым и просто отображает все, что ему передается.

Запустите сервер с помощью npm start и обновляйте страницу столько раз, сколько хотите — теперь конфиг выгружается из файла и никаких запросов к удаленному серверу не делается. Вы можете убедиться в этом, время от времени заглядывая на вкладку «Использование и квоты». Вы также можете найти необработанную конфигурацию в локальном файле.

3. Позаботьтесь об обновлениях кеша

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

Ответ прост — вебхуки.

Вебхуки настраиваются в пользовательском интерфейсе ConfigCat в пару кликов. Вы можете указать один или несколько веб-хуков для клиента — то есть для комбинации конфигурации и среды.

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

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

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

Теперь вернемся к пользовательскому интерфейсу ConfigCat и изменим конфигурацию нашего флага. На этот раз мы хотим отображать флажок только в том случае, если пользователь НЕ использует мобильное устройство, поэтому мы хотим сопоставить поле isMobile со строкой «false», а не «true».

Поскольку я разрабатываю на локальном хосте, а указанный в вебхуке URL-адрес — просто подделка, я буду вызывать конечную точку моего локального сервера из терминала. Вы можете поверить мне на слово, что ConfigCat сделает то же самое удаленно.

curl http://localhost:3000/api/configcatwebhook

Теперь давайте обновим страницу.

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

Подводя итог

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

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

Я надеюсь, что эта информация была вам полезна, и желаю вам отлично провести время за кодированием!