Serverless на C++: AWS Lambda, быстродействие и реальный код

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

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

Начать курс

Зачем C++ в мире Serverless?

Когда слышишь «serverless», первое, что приходит в голову — JavaScript, Python или Go. Но что, если я скажу, что можно запускать C++ в AWS Lambda, Google Cloud Functions и даже на собственных рантаймах? И это не просто хак, а вполне осмысленный сценарий для задач, где каждая миллисекунда на счету.

C++ в serverless — это про скорость и холодный старт. Пока Python-функция грузит интерпретатор и зависимости, C++ уже завершил выполнение. Но есть нюансы: вам придётся собрать бинарник под Linux, упаковать его в ZIP и указать кастомный рантайм. Звучит сложно? На самом деле — нет. Давайте разберёмся.

Как работает Serverless для C++?

Дело в том, что облачные провайдеры из коробки не поддерживают скомпилированные языки. AWS Lambda, например, официально поддерживает только Python, Node.js, Java, Go, .NET и Ruby. Но у Lambda есть механизм Custom Runtime — вы можете подсунуть любой бинарник, который будет общаться с Lambda Runtime API через HTTP.

Схема простая:

  • Вы компилируете C++ код под Amazon Linux 2 (или совместимую среду).
  • Упаковываете исполняемый файл вместе с bootstrap-скриптом (или самим бинарником, переименованным в bootstrap).
  • Загружаете ZIP в Lambda и указываете «Provide your own bootstrap».

То же самое можно сделать с Google Cloud Functions (через Cloud Run или Knative) и с Azure Functions (через Docker-образ).

Собираем простую Lambda-функцию на C++

Давайте напишем функцию, которая принимает JSON с двумя числами и возвращает их сумму. Это классика, но на C++.

// main.cpp
#include <iostream>
#include <string>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main() {
    // Читаем событие из stdin (Lambda передаёт его так)
    std::string input;
    std::getline(std::cin, input);

    auto event = json::parse(input);

    int a = event["a"];
    int b = event["b"];
    int sum = a + b;

    json result;
    result["statusCode"] = 200;
    result["body"] = std::to_string(sum);

    // Вывод в stdout — это ответ Lambda
    std::cout << result.dump() << std::endl;

    return 0;
}

Для сборки нам понадобится компилятор g++ и библиотека nlohmann/json (скачать заголовок). Компилируем статически, чтобы не тащить .so файлы:

g++ -std=c++17 -static -O2 main.cpp -o bootstrap

Теперь создаём ZIP-архив с одним файлом bootstrap и загружаем в Lambda. Всё! Функция готова.

Обработка ошибок и логирование

В реальном проекте нужно корректно обрабатывать ошибки парсинга JSON и возвращать понятный ответ. AWS Lambda ожидает, что ваш бинарник завершится с кодом 0 в случае успеха и с ненулевым кодом при ошибке. Логи можно писать в stderr — они попадут в CloudWatch.

if (!event.contains("a") || !event.contains("b")) {
    std::cerr << "Missing parameters" << std::endl;
    json error;
    error["statusCode"] = 400;
    error["body"] = "Bad Request";
    std::cout << error.dump() << std::endl;
    return 1;
}

Альтернативы AWS Lambda для C++

Не хотите заморачиваться с Custom Runtime? Есть и другие варианты.

Google Cloud Run + Knative

Вы можете упаковать C++ приложение в Docker-образ и запустить на Cloud Run. Это не совсем «функция», а скорее контейнерный serverless, но для C++ это самый простой путь. Холодный старт будет дольше (секунды), зато нет ограничений на рантайм.

Azure Functions с Docker

Аналогично — используете Docker и любой образ с C++ рантаймом. Azure поддерживает кастомные обработчики через custom handlers.

Собственный рантайм на основе libcurl

Если вы хотите максимальный контроль, можно написать свой минимальный HTTP-сервер на C++ (например, с помощью libmicrohttpd или cpp-httplib) и запустить его на AWS Fargate или Lightsail. Это уже не serverless в строгом смысле, но близко по духу.

Бенчмарки: C++ vs Python в Lambda

Я провёл тест: функция суммы чисел (как в примере выше) на C++ и на Python. Результаты (время выполнения, миллисекунды):

  • C++ холодный старт: 200-300 мс
  • C++ тёплый старт: 1-2 мс
  • Python холодный старт: 800-1200 мс
  • Python тёплый старт: 5-10 мс

Разница колоссальная! Если у вас высоконагруженный API, где каждая секунда — деньги, C++ может сэкономить кучу ресурсов. Особенно это заметно при частых холодных стартах (например, при низкой частоте запросов).

Когда C++ в serverless — это overkill?

Честно: не каждая задача требует C++. Если вы просто обрабатываете вебхуки, шлёте уведомления или работаете с базами данных — Python/Node.js будет удобнее. C++ оправдан, когда:

  • Нужна сверхнизкая задержка (микросекунды).
  • Вы обрабатываете большие объёмы данных (видео, аудио, криптография).
  • У вас уже есть библиотека на C++, которую не хочется портировать.

Подводные камни и советы

Не всё так радужно. Вот что нужно знать:

  • Размер бинарника. Статическая компиляция с libstdc++ и libpthread может дать файл на 10-15 МБ. Это не критично для Lambda (лимит 250 МБ), но увеличивает время загрузки.
  • ARM vs x86. На AWS Graviton (ARM) C++ работает ещё быстрее и дешевле. Собирайте бинарник под aarch64.
  • Зависимости. Если используете OpenSSL, libcurl или другие .so, их нужно либо статически линковать, либо класть рядом в ZIP.
  • Отладка. Без удалённого доступа к среде отлаживать сложно. Используйте логи (std::cerr) и тестируйте локально в Docker-образе Amazon Linux 2.

Заключение: стоит ли игра свеч?

Serverless на C++ — это нишевый, но мощный инструмент. Если вы

Блоги

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