📲 Что такое Backends for Frontends и когда стоит его использовать
|
Backends for Frontends – это паттерн, который предполагает разработку отдельных бэкенд-сервисов, оптимизированных под фронтенд конкретных приложений (веб, мобильные, IoT и т. д.). Каждый BFF создает API, идеально подходящий для своего клиента. BFF можно рассматривать как развитие концепции API Gateway, однако между ними есть несколько ключевых отличий: |
- API Gateway обычно предоставляет единую точку входа для всех клиентов, а BFF создает отдельные шлюзы для каждого типа клиента (веб, мобильный и т. д.).
- BFF более специализирован и ориентирован на конкретные нужды разных типов фронтендов, а API Gateway более универсален и может обслуживать разные клиенты без специфической оптимизации.
- BFF больше фокусируется на оптимизации взаимодействия между конкретным фронтендом и бэкендом, в то время как API Gateway часто используется для общих задач (маршрутизация, аутентификация, балансировка нагрузки).
|
- API Gateway перенаправляет запросы на соответствующий BFF.
- BFF взаимодействует с нужными микросервисами (например, Products, Orders, Cart).
- BFF обрабатывает и оптимизирует данные для конкретного клиента.
|
Универсальный API vs BFF для каждого типа клиента |
Паттерн появился в 2015 году, приобрел широкую известность к 2021-му и с тех пор остается одним из самых популярных подходов в разработке микросервисов. На это есть веские причины: |
- Оптимизация производительности – BFF позволяет настроить потоки данных и форматы ответов для каждого фронтенда, повышая скорость работы приложений.
- Улучшенная безопасность – изоляция фронтендов дает возможность реализовать меры безопасности, учитывающие специфику каждого клиента.
- Гибкость разработки – фронтендеры и бэкендеры могут работать более независимо, в отдельных командах, ускоряя процесс создания и обновления продукта.
- Упрощение фронтенд-разработки – BFF предоставляет именно те данные, которые нужны конкретному интерфейсу, избавляя от лишней обработки на клиенте.
- Упрощение поддержки и модификации API для каждого отдельного фронтенда.
|
Когда стоит использовать BFF: |
- Когда у сервиса несколько типов клиентов с разными потребностями в данных.
- Если необходима серьезная оптимизация производительности для конкретных интерфейсов.
|
Например, BFF будет оптимальным выбором для: |
- E-commerce платформ – отдельные BFF для веб-сайта, мобильных приложений и умных устройств будут обрабатывать специфические потоки данных и действия пользователей.
- Финансовых сервисов – специализированные BFF для веб- и мобильного банкинга обеспечат более удобное и безопасное использование сервиса.
- CMS – паттерн упростит адаптивную доставку контента для разных устройств.
|
✍️ Как написать HTTP-сервер на Go
|
Платформа CodeCrafters предлагает практичный подход к обучению – разработчики там учатся и совершенствуют навыки в процессе создания реальных, готовых к использованию приложений. Например, одно из заданий – разработка HTTP-сервера. Студент успешно выполнил задание на Go без использования сторонних библиотек и рассказал о процессе работы в этом пошаговом туториале. Основные характеристики и функциональность сервера:
|
- Базовый TCP-сервер, слушающий порт 4221.
- Обрабатывает HTTP-запросы и отправляет соответствующие ответы.
- Поддерживает разные маршруты и HTTP-методы.
- Обрабатывает параметры URL и заголовки запросов.
- Поддерживает отправку файлов в ответ на запросы.
- Предусматривает конкурентную обработку нескольких соединений.
|
Для каждого нового соединения запускается отдельная горутина |
Этот проект отлично подходит для начинающих разработчиков – помогает понять, как работают веб-серверы под капотом, без абстракций, предоставляемых высокоуровневыми фреймворками. Процесс создания аналогичного сервера на Python подробно рассмотрен здесь. |
☢️ Почему не стоит использовать as в Rust
|
Оператор as используется для приведения типов: позволяет преобразовывать значения одного типа в другой. Но, как пишет опытный Rust-разработчик, использование as может привести к неожиданному поведению при преобразовании в меньший тип данных: если значение не помещается в целевой тип, происходит усечение без предупреждения – это приводит к появлению трудноотслеживаемых ошибок в больших проектах. Например, у нас есть число 288, которое мы хотим преобразовать в тип u8 (8-битное беззнаковое целое число). Тип u8 может хранить значения от 0 до 255. Очевидно, 288 не помещается в этот диапазон. При использовании as для преобразования вместо ожидаемой ошибки или предупреждения Rust выполняет усечение значения. В этом случае результат будет равен 32: |
- 288 в двоичном виде: 100100000.
- При преобразовании в u8 Rust берет только 8 младших битов (справа налево): 00100000.
- 00100000 в десятичной системе равно 32.
|
Это поведение станет полной неожиданностью для программистов, переключившихся на Rust с языков высокого уровня, где подобные преобразования всегда вызывают ошибки или предупреждения. Лучшее решение этой проблемы – использовать трейт TryFrom вместо as. Этот подход требует чуть больше кода, но это один из тех немногих случаев, когда отказ от стандартного приема действительно оправдан: |
TryFrom явно обрабатывает случаи, когда значение не помещается в целевой тип данных |
🐍 Как создать инвертированный индекс на Python
|
Инвертированный индекс – это структура данных, которая позволяет быстро находить документы, содержащие определенное слово или фразу. Главные преимущества инвертированного индекса: |
- Высокая скорость – поиск по индексу значительно быстрее, чем полный просмотр всех документов.
- Эффективность для больших объемов данных – индекс позволяет эффективно обрабатывать большие коллекции документов.
|
Вместо того, чтобы просматривать каждый документ целиком, индекс хранит информацию о том, в каких документах встречается каждое слово. Для этого он использует хэш-таблицу (словарь в случае Python), где ключами являются слова, а значениями – списки идентификаторов документов, содержащих эти слова. Общий принцип построения индекса выглядит так: |
- Определяется структура документов (например, название и текст статьи).
- Создается список документов.
|
- Преобразуется текст – переводится в нижний регистр, удаляются знаки препинания.
- Обработанный текст разбивается на слова.
|
- Если слово еще не в индексе, создается запись с пустым списком документов.
- Добавляется идентификатор текущего документа в список для данного слова.
|
Алгоритм поиска по индексу включает в себя: |
- Запрос приводится к нижнему регистру и очищается от знаков препинания.
- Преобразованный запрос разбивается на слова.
|
Для каждого слова в запросе: |
- Находится список документов для этого слова в индексе.
- Объединяются списки документов для всех слов запроса.
|
- По идентификаторам из объединенного списка находятся соответствующие документы.
|
Сравнение скорости выполнения 20 запросов по 15 000 документов |
🛠️ 18 основных паттернов микросервисной архитектуры
|
В этой статье подробно рассказано о паттернах, которые представляют собой набор проверенных решений типичных проблем и задач в микросервисной архитектуре. Их правильное применение может значительно улучшить масштабируемость, надежность и гибкость системы. 1. Service Registry (Реестр сервисов)
Этот паттерн решает проблему обнаружения сервисов в распределенной системе. Каждый микросервис регистрирует себя в центральном реестре (например, Netflix Eureka или Consul). Когда одному сервису нужно взаимодействовать с другим, он обращается к реестру, чтобы узнать текущий адрес нужного сервиса. Это позволяет сервисам динамически обнаруживать друг друга без жесткой привязки к конкретным адресам.
2. API Gateway (API-шлюз)
API Gateway действует как единая точка входа для всех клиентских запросов. Он принимает запросы от клиентов и перенаправляет их соответствующим микросервисам. API Gateway может также выполнять такие задачи, как аутентификация, авторизация и балансировка нагрузки. Это упрощает взаимодействие клиентов с системой, скрывая сложность внутренней архитектуры.
3. Circuit Breaker (Предохранитель)
Этот паттерн предотвращает каскадные сбои в системе. Когда один сервис начинает давать сбои, Circuit Breaker временно блокирует запросы к этому сервису, предотвращая перегрузку и позволяя системе восстановиться. Это повышает устойчивость системы и помогает избежать полного отказа всей системы из-за проблем с одним сервисом.
4. Bulkhead (Отсек)
Паттерн Bulkhead изолирует компоненты системы друг от друга, чтобы сбой в одной части не повлиял на другие. Например, для разных сервисов могут использоваться отдельные пулы потоков или базы данных. Это повышает устойчивость системы и ограничивает распространение сбоев. 5. Saga Pattern (Сага)
Saga используется для управления распределенными транзакциями в микросервисной архитектуре. Длительная бизнес-операция разбивается на серию меньших, локальных транзакций. Каждый сервис выполняет свою часть транзакции и публикует событие, которое запускает следующий шаг. Если что-то идет не так, выполняются компенсирующие действия для отмены изменений.
|
Принцип работы паттерна Сага |
6. Event Sourcing (Источник событий) Вместо хранения только текущего состояния этот паттерн сохраняет все события, которые привели к этому состоянию. Это обеспечивает надежный аудиторский след и позволяет восстановить состояние системы на любой момент времени. Особенно полезен в системах, где важна история изменений и возможность отката.
7. Command Query Responsibility Segregation (CQRS, Разделение команд и запросов)
CQRS разделяет операции чтения и записи в приложении. Используются разные модели для обновления информации (команды) и чтения информации (запросы). Это позволяет оптимизировать каждую сторону независимо, что может значительно улучшить производительность и масштабируемость.
8. Data Sharding (Шардинг данных)
Этот паттерн используется для распределения нагрузки на базу данных. Данные разделяются на несколько баз данных или экземпляров базы данных. Каждый микросервис может обрабатывать подмножество данных или определенные типы запросов. Это помогает избежать узких мест в работе с данными и улучшает масштабируемость.
9. Polyglot Persistence (Многовариантное хранение)
Этот подход позволяет использовать разные технологии баз данных для разных микросервисов, исходя из их конкретных потребностей. Например, один сервис может использовать реляционную БД, другой – NoSQL, третий – графовую БД. Это оптимизирует хранение, извлечение и обработку данных для каждого сервиса.
|
Реализация многовариантного хранения в Azure |
10. Retry (Повторная попытка) Обеспечивает повторение операции при возникновении временного сбоя – вместо немедленного отказа. Может применяться на разных уровнях: от взаимодействия между сервисами до работы с базой данных. Помогает справиться с кратковременными проблемами в сети или сервисах.
11. Sidecar (Вспомогательный сервис)
Этот паттерн предполагает присоединение вспомогательного сервиса (sidecar) к основному микросервису для обеспечения дополнительной функциональности, такой как логирование, безопасность или коммуникация с внешними сервисами. Позволяет основному сервису сосредоточиться на своей основной функции.
12. Backends for Frontends (BFF, Бэкенды для фронтендов)
BFF предполагает создание отдельных бэкенд-сервисов для каждого типа клиента (веб, мобильный и т. д.). Это позволяет оптимизировать API под конкретные нужды каждого клиента, улучшая производительность и упрощая разработку клиентской части.
13. Shadow Deployment (Теневое развертывание)
Этот паттерн предполагает отправку копии (тени) производственного трафика к новой версии микросервиса без влияния на реальный пользовательский опыт. Это позволяет проверить производительность и корректность новой версии в реальных условиях, не подвергая риску текущих пользователей.
14. Consumer-Driven Contracts (Контракты, определяемые потребителем)
В этом подходе потребители сервисов определяют свои ожидания от поставщиков сервисов. Это помогает обеспечить более надежные и согласованные изменения в системе. Каждый сервис-потребитель описывает, какой именно функционал и в каком формате он ожидает от сервиса-поставщика.
15. Smart Endpoints, Dumb Pipes (Умные конечные точки, глупые каналы)
Этот паттерн рекомендует размещать бизнес-логику в самих микросервисах (умные конечные точки), а не полагаться на сложное промежуточное ПО. Инфраструктура коммуникаций (каналы) должна быть простой и заниматься только маршрутизацией сообщений. Это упрощает систему и делает ее более гибкой.
16. Database per Service (База данных для каждого сервиса)
В этом паттерне каждый микросервис имеет свою собственную базу данных, и сервисы общаются через четко определенные API. Это обеспечивает изоляцию данных и независимость сервисов, но требует тщательного подхода к обеспечению согласованности данных между сервисами.
17. Async Messaging (Асинхронный обмен сообщениями)
Вместо синхронного взаимодействия между микросервисами этот паттерн предполагает использование очередей сообщений для асинхронной коммуникации. Это может улучшить отзывчивость системы и ее масштабируемость, так как сервисы не блокируются в ожидании ответа друг от друга.
18. Stateless Services (Сервисы без состояния)
Проектирование микросервисов как stateless (без сохранения состояния) упрощает масштабирование и повышает устойчивость. Каждый сервис обрабатывает запрос независимо, не полагаясь на сохраненное состояние – это облегчает горизонтальное масштабирование.
|
|
|
Понравилась ли вам эта рассылка? |
|
|
Вы получили это письмо, потому что подписались на нашу рассылку. Если вы больше не хотите получать наши письма, нажмите здесь.
|
|
|
|