Понимание шаблона API-шлюза в микросервисах: простое руководство
Переход от единого монолитного приложения к микросервисной архитектуре решает множество проблем. Это позволяет командам работать независимо, развертывать сервисы отдельно и масштабировать части системы по мере необходимости. Однако возникает и новая проблема: как клиенты взаимодействуют со всеми этими независимыми сервисами?
Если у вас есть десять, пятьдесят или сотни крошечных микросервисов, должно ли мобильное приложение или веб-страница подключаться к каждому из них напрямую?
Именно здесь на помощь приходит Шаблон API-шлюза. В этом руководстве мы разберем, что такое API-шлюз, зачем он вам нужен и как он упрощает вашу систему микросервисов, используя простые слова и аналогии из реальной жизни.
Реальная аналогия: администратор отеля
Представьте, что вы останавливаетесь в большом роскошном курортном отеле. На курорте много разных отделений:
- Уборка номеров (за чистое постельное белье)
- Обслуживание номеров (еда)
- Консьерж (для бронирования туров)
- Биллинг (для оплаты счета)
Если вам нужно чистое полотенце, вам не придется ходить по курорту, пытаясь найти здание горничной. Если хочешь поужинать, не стучи в кухонную дверь. Вместо этого вы звоните администратору стойки регистрации.
Администратор выслушивает ваш запрос, определяет, какой отдел может его решить, и соединяет вас или обрабатывает его за вас.
В этом сценарии:
- Вы являетесь Клиентом (мобильное приложение или браузер).
- Администратор — это Шлюз API.
- Отделы (уборка номеров, обслуживание номеров, выставление счетов) — это микрослужбы.
Проблема: прямое общение клиента с сервисом
Прежде чем рассмотреть, как работает шлюз, давайте посмотрим, что произойдет, если мы не воспользуемся им.
Предположим, что ваше приложение электронной коммерции имеет три отдельных микросервиса:
- Служба пользователей (управление профилями)
- Служба продуктов (управляет каталогом)
- Сервис заказа (управляет оформлением заказа)
Без шлюза API клиентское приложение должно отправлять отдельные запросы непосредственно на индивидуальный адрес каждой службы (IP или URL):
Такой подход с прямым подключением создает несколько серьезных проблем:
- Слишком много конечных точек. Клиентское приложение должно запомнить три отдельных URL-адреса. Если вы разделили сервис или изменили его адрес, вам придется обновить клиентское приложение.
- Кошмар безопасности: каждый микросервис должен отдельно реализовывать аутентификацию (проверку токенов входа), SSL-сертификаты и правила брандмауэра.
- Сетевые издержки. Клиенту может потребоваться выполнить три отдельных сетевых запроса через медленные мобильные сети только для загрузки одной страницы (например, получение профиля, получение сведений о продукте и получение истории заказов).
- Различия в протоколах. Ваше клиентское приложение может предпочитать использовать стандартные веб-протоколы, такие как HTTP/JSON, но ваши внутренние службы могут взаимодействовать быстрее, используя специализированные протоколы, такие как gRPC или AMQP.
Решение: шаблон API-шлюза
API-шлюз — это вспомогательный сервер, расположенный между клиентскими приложениями и внутренними микрослужбами. Он действует как единая точка входа для всех входящих запросов.
Вместо вызова трех разных служб клиент выполняет один вызов API-шлюза. Затем шлюз пересылает запрос нужной внутренней службе, собирает результаты и отправляет их обратно клиенту.
Ключевые обязанности API-шлюза
API-шлюз делает гораздо больше, чем просто прямой трафик. Он решает «сквозные проблемы» — задачи, для которых в противном случае каждому микросервису пришлось бы писать код:
- Маршрутизация. Шлюз принимает входящий URL-адрес (например,
/api/v1/orders) и сопоставляет его с правильным внутренним адресом службы. - Аутентификация и авторизация. Шлюз проверяет токены безопасности (например, JWT) на входной двери. Если запрос недействителен, он немедленно отклоняется, что избавляет ваши микросервисы от траты ресурсов ЦП на неаутентифицированные запросы.
- Ограничение скорости: оно предотвращает рассылку спама в вашу систему вредоносными ботами или клиентами с ошибками, ограничивая количество запросов, которые пользователь может сделать в минуту.
- Балансировка нагрузки. Шлюз может равномерно распределять входящий трафик между несколькими экземплярами микросервиса, чтобы предотвратить перегрузку любого отдельного сервера.
- Трансляция протокола. Он может преобразовывать запросы JSON, обращенные к пользователю, в высокопроизводительные внутренние сообщения gRPC, позволяя службам общаться друг с другом на предпочитаемых ими языках.
Простая реализация: пример кода
Чтобы увидеть, насколько упрощается маршрутизация, давайте рассмотрим два распространенных способа настройки шлюза API.
1. Декларативная маршрутизация (YAML Spring Cloud Gateway)
В корпоративных Java-системах маршрутизацию часто настраивают с помощью простого файла конфигурации. Шлюз автоматически пересылает запросы на основе следующих правил:
spring:
cloud:
gateway:
routes:
- id: user_service_route
uri: http://internal-user-service:8081
predicates:
- Path=/api/users/**
- id: product_service_route
uri: http://internal-product-service:8082
predicates:
- Path=/api/products/**
2. Программная маршрутизация (макет шлюза Node.js)
Если вы хотите создать облегченный шлюз API на Javascript с использованием Express, это выглядит так:
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const PORT = 3000;
// 1. Simple Security/Authentication Check at the door
const authenticate = (req, res, next) => {
const token = req.headers['authorization'];
if (token === 'secret-handshake-token') {
next(); // Token is valid, proceed
} else {
res.status(401).json({ error: 'Unauthorized Access!' });
}
};
// Apply auth check to all incoming gateway requests
app.use(authenticate);
// 2. Route requests to correct internal microservices
app.use('/api/users', createProxyMiddleware({ target: 'http://localhost:8081', changeOrigin: true }));
app.use('/api/products', createProxyMiddleware({ target: 'http://localhost:8082', changeOrigin: true }));
app.use('/api/orders', createProxyMiddleware({ target: 'http://localhost:8083', changeOrigin: true }));
app.listen(PORT, () => {
console.log(`API Gateway running smoothly on port ${PORT}`);
});
Плюсы и минусы шаблона шлюза API
Как и любое архитектурное решение, использование API-шлюза имеет свои недостатки:
| Преимущество (Про) | Недостаток (Против) |
|---|---|
| Простой клиентский интерфейс: клиентам нужно знать только одно доменное имя. | Единая точка отказа: если шлюз выходит из строя, все приложение становится недоступным. |
| Централизованная безопасность: реализуйте проверки входа, SSL и CORS в одном месте. | Дополнительная задержка. Запросы выполняются немного дольше, поскольку им приходится проходить дополнительный сетевой переход. |
| Уменьшение дублирования кода. Избегайте переписывания кода аутентификации и ограничения скорости в каждом сервисе. | Накладные расходы на обслуживание: шлюз необходимо обновлять при каждом добавлении, удалении или разделении служб. |
Заключение
Шаблон API Gateway — краеугольный камень современной архитектуры микросервисов. Действуя как единая интеллектуальная точка входа, он защищает клиентские приложения от сложностей настройки внутренних служб. Он упрощает код на стороне клиента, централизует безопасность и эффективно управляет трафиком.
Несмотря на то, что он требует незначительного сетевого перехода и требует настройки с высокой доступностью в рабочей среде, преимущества более чистых, безопасных и управляемых кодовых баз делают его настоятельно рекомендуемым шаблоном для любой растущей распределенной системы.
Узнайте больше о разработке программного обеспечения и внутренней инженерии в блоге Ghaznix →