Зачем 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++ — это нишевый, но мощный инструмент. Если вы