Понимание шаблона API-шлюза в микросервисах: простое руководство

Понимание шаблона API-шлюза в микросервисах: простое руководство

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

Если у вас есть десять, пятьдесят или сотни крошечных микросервисов, должно ли мобильное приложение или веб-страница подключаться к каждому из них напрямую?

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


Реальная аналогия: администратор отеля

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

  • Уборка номеров (за чистое постельное белье)
  • Обслуживание номеров (еда)
  • Консьерж (для бронирования туров)
  • Биллинг (для оплаты счета)

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

Администратор выслушивает ваш запрос, определяет, какой отдел может его решить, и соединяет вас или обрабатывает его за вас.

В этом сценарии:

  • Вы являетесь Клиентом (мобильное приложение или браузер).
  • Администратор — это Шлюз API.
  • Отделы (уборка номеров, обслуживание номеров, выставление счетов) — это микрослужбы.

Проблема: прямое общение клиента с сервисом

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

Предположим, что ваше приложение электронной коммерции имеет три отдельных микросервиса:

  1. Служба пользователей (управление профилями)
  2. Служба продуктов (управляет каталогом)
  3. Сервис заказа (управляет оформлением заказа)

Без шлюза API клиентское приложение должно отправлять отдельные запросы непосредственно на индивидуальный адрес каждой службы (IP или URL):

Схема архитектуры шлюза API, показывающая маршрутизацию, безопасность и микросервисы

Такой подход с прямым подключением создает несколько серьезных проблем:

  • Слишком много конечных точек. Клиентское приложение должно запомнить три отдельных URL-адреса. Если вы разделили сервис или изменили его адрес, вам придется обновить клиентское приложение.
  • Кошмар безопасности: каждый микросервис должен отдельно реализовывать аутентификацию (проверку токенов входа), SSL-сертификаты и правила брандмауэра.
  • Сетевые издержки. Клиенту может потребоваться выполнить три отдельных сетевых запроса через медленные мобильные сети только для загрузки одной страницы (например, получение профиля, получение сведений о продукте и получение истории заказов).
  • Различия в протоколах. Ваше клиентское приложение может предпочитать использовать стандартные веб-протоколы, такие как HTTP/JSON, но ваши внутренние службы могут взаимодействовать быстрее, используя специализированные протоколы, такие как gRPC или AMQP.

Решение: шаблон API-шлюза

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

Вместо вызова трех разных служб клиент выполняет один вызов API-шлюза. Затем шлюз пересылает запрос нужной внутренней службе, собирает результаты и отправляет их обратно клиенту.

Ключевые обязанности API-шлюза

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

  1. Маршрутизация. Шлюз принимает входящий URL-адрес (например, /api/v1/orders) и сопоставляет его с правильным внутренним адресом службы.
  2. Аутентификация и авторизация. Шлюз проверяет токены безопасности (например, JWT) на входной двери. Если запрос недействителен, он немедленно отклоняется, что избавляет ваши микросервисы от траты ресурсов ЦП на неаутентифицированные запросы.
  3. Ограничение скорости: оно предотвращает рассылку спама в вашу систему вредоносными ботами или клиентами с ошибками, ограничивая количество запросов, которые пользователь может сделать в минуту.
  4. Балансировка нагрузки. Шлюз может равномерно распределять входящий трафик между несколькими экземплярами микросервиса, чтобы предотвратить перегрузку любого отдельного сервера.
  5. Трансляция протокола. Он может преобразовывать запросы 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 →