API Gateway для C++ сервисов: от идеи до продакшена

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

API Gateway для C++ сервисов: когда производительность решает всё

Представьте: у вас десяток микросервисов на C++, каждый — настоящий зверь производительности. Клиенты шлют тысячи запросов в секунду, а система начинает тормозить из-за... шлюза. Знакомая боль? Чаще всего разработчики тянут в C++-экосистему Nginx с Lua или тяжеловесный Kong, хотя могли бы написать свой API Gateway на C++ — быстрый, легкий и предсказуемый.

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

Зачем писать API Gateway на C++?

Давайте честно: большинство проектов не нуждаются в кастомном шлюзе. Nginx, Envoy или Kong решают 90% задач. Но есть сценарии, где C++ незаменим:

  • Задержки менее 1 мс — финансовые системы, гейм-серверы, real-time трейдинг
  • Миллионы RPS — высоконагруженные API, CDN, IoT-платформы
  • Жесткие требования к памяти — embedded-системы, edge-устройства
  • Тесная интеграция с C++-кодом — вызов нативных библиотек без накладных расходов

Кроме того, API Gateway C++ дает полный контроль над каждым байтом. Вы сами решаете, как обрабатывать заголовки, как кешировать, как балансировать нагрузку. Никакой магии — только предсказуемая производительность.

Архитектура API Gateway на C++

Типичный шлюз API на C++ состоит из нескольких слоев:

  1. Транспортный слой — прием и отправка HTTP-запросов (boost::beast, libcurl, собственный сокет)
  2. Маршрутизатор — сопоставление URL с бэкенд-сервисами
  3. Middleware — аутентификация, rate limiting, логирование, CORS
  4. Балансировщик — round-robin, least-connections, взвешенный
  5. Кеш — in-memory кеш ответов (LRU, LFU)

Вот как это выглядит схематично:

Client → [API Gateway C++] → Middleware → Router → Balancer → Backend A
                               ↓
                           [Cache]

Каждый слой — это отдельный модуль. Их можно компоновать как конструктор. Хотите добавить JWT-валидацию? Пишете middleware. Нужен новый алгоритм балансировки? Добавляете класс.

Пишем API Gateway на C++: боевой пример

Возьмем современный C++20 и библиотеку boost::beast для HTTP. Наш шлюз будет:

  • Принимать запросы на порту 8080
  • Маршрутизировать по префиксу URL
  • Проверять API-ключ
  • Ограничивать 100 запросов в минуту на IP
  • Балансировать между двумя бэкендами

Шаг 1: Базовая структура

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <unordered_map>
#include <memory>
#include <string>

namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using tcp = net::ip::tcp;

// Структура для хранения информации о бэкенде
struct Backend {
    std::string host;
    std::string port;
    int weight;
};

// Класс маршрутизатора
class Router {
    std::unordered_map<std::string, std::vector<Backend>> routes_;
    std::unordered_map<std::string, size_t> counters_; // round-robin

public:
    void add_route(const std::string& prefix, std::vector<Backend> backends) {
        routes_[prefix] = std::move(backends);
        counters_[prefix] = 0;
    }

    Backend get_backend(const std::string& path) {
        for (const auto& [prefix, backends] : routes_) {
            if (path.find(prefix) == 0) {
                // Round-robin балансировка
                size_t idx = counters_[prefix]++ % backends.size();
                return backends[idx];
            }
        }
        throw std::runtime_error("No route found");
    }
};

Шаг 2: Middleware для rate limiting

Реализуем простой скользящий счетчик:

#include <chrono>
#include <map>

class RateLimiter {
    std::map<std::string, std::pair<int, std::chrono::steady_clock::time_point>> clients_;
    int max_requests_;
    std::chrono::seconds window_;

public:
    RateLimiter(int max_reqs, std::chrono::seconds win) 
        : max_requests_(max_reqs), window_(win) {}

    bool allow(const std::string& ip) {
        auto now = std::chrono::steady_clock::now();
        auto& [count, reset_time] = clients_[ip];

        if (now > reset_time + window_) {
            count = 0;
            reset_time = now;
        }

        if (count >= max_requests_) return false;
        ++count;
        return true;
    }
};

Шаг 3: Обработчик запросов

Сердце нашего API Gateway на C++ — функция, которая принимает запрос, прогоняет через middleware и отправляет на бэкенд:

template<class Stream>
void handle_request(Stream& stream, http::request<http::string_body>& req, 
                    Router& router, RateLimiter& limiter) {
    
    // 1. Rate limiting
    auto ip = stream.remote_endpoint().address().to_string();
    if (!limiter.allow(ip)) {
        http::response<http::string_body> res{http::status::too_many_requests, req.version()};
        res.body() = R"({"error":"rate_limit_exceeded"})";
        res.prepare_payload();
        http::write(stream, res);
        return;
    }

    // 2. Аутентификация (упрощенно)
    auto api_key = req[http::field::authorization];
    if (api_key.empty() || api_key != "Bearer my-secret-key") {
        http::response<http::string_body> res{http::status::unauthorized, req.version()};
        res.body() = R"({"error":"invalid_api_key"})";
        res.prepare_payload();
        http::write(stream, res);
        return;
    }

    // 3. Маршрутизация
    Backend backend;
    try {
        backend = router.get_backend(req.target().to_string());
    } catch (...) {
        http::response<http::string_body> res{http::status::not_found, req.version()};
        res.body() = R"({"error":"route_not_found"})";
        res.prepare_payload();
        http::write(stream, res);
        return;                

Блоги

Рекомендаций по книгам