Serverless на Rust: Когда каждая миллисекунда на счету
Вы когда-нибудь ждали запуска AWS Lambda целых 3-4 секунды? Если вы работали с Python или Node.js в serverless-среде, то знакомы с этой болью — холодный старт. Теперь представьте: ваша функция запускается за 50-100 миллисекунд, потребляет в 10 раз меньше памяти, а бинарник весит всего 5 мегабайт. Добро пожаловать в мир serverless функций на Rust.
Rust ворвался в serverless не просто так. Это язык, который даёт контроль над памятью без сборщика мусора, компилируется в нативный код и идеально подходит для edge-вычислений. На PythonLib мы обожаем Python, но когда речь идёт о скорости и стоимости — особенно при высоких нагрузках — Rust становится убийцей.
В этой статье мы разберём:
- Почему Rust — лучший язык для serverless (спойлер: не только из-за скорости)
- Как написать и развернуть AWS Lambda на Rust
- Альтернативы: Cloudflare Workers и Vercel Edge Functions
- Бенчмарки холодного старта Rust vs Python
Готовы? Погнали.
Почему Rust для Serverless — это не хайп, а математика
Давайте сразу к цифрам. Средний холодный старт AWS Lambda на Python — 400-800 мс (с загрузкой зависимостей). На Node.js — 200-400 мс. На Rust — 30-100 мс. Почему такая разница?
- Нет интерпретатора или JIT. Rust компилируется в машинный код. Lambda просто загружает бинарник — и готово.
- Минимальный размер. Даже с tokio и serde бинарник весит 5-15 МБ (сжатый zip — 2-4 МБ). Python с numpy или pandas — 50-200 МБ.
- Экономия памяти. Rust-функции потребляют 20-50 МБ против 128-256 МБ для Python. На 10 миллионах запросов разница в счете — сотни долларов.
Но есть нюанс: писать на Rust сложнее. Нужно понимать владение, lifetimes, async. Однако, если ваша Lambda — критичный микросервис с RPS > 1000, Rust окупается быстро.
Практика: Пишем AWS Lambda на Rust
Шаг 1: Установка инструментов
Вам понадобятся:
- Rust (rustup)
- cargo-lambda — утилита для сборки под AWS
- Docker (для сборки под Linux, если у вас macOS/Windows)
# Устанавливаем cargo-lambda
cargo install cargo-lambda
# Создаём новый проект
cargo lambda new my-rust-lambda
cd my-rust-lambda
Шаг 2: Код функции
Откройте src/main.rs. Стандартный шаблон уже содержит базовую структуру. Давайте напишем что-то полезное — API, которое принимает JSON с именем и возвращает приветствие.
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Request {
name: String,
}
#[derive(Serialize)]
struct Response {
message: String,
timestamp: u64,
}
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
let request = event.payload;
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
Ok(Response {
message: format!("Привет, {}! Ты на PythonLib, но мы на Rust 🦀", request.name),
timestamp,
})
}
#[tokio::main]
async fn main() -> Result<(), Error> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.init();
run(service_fn(handler)).await
}
Шаг 3: Сборка и деплой
# Сборка под Linux (для Lambda)
cargo lambda build --release
# Деплой (нужны AWS credentials)
cargo lambda deploy --iam-role arn:aws:iam::YOUR_ACCOUNT:role/lambda-execution-role
Готово! Теперь у вас есть Lambda на Rust, которая работает в 5-10 раз быстрее Python-аналога.
Альтернативы AWS Lambda: Cloudflare Workers и Vercel
AWS — не единственная опция. Если вам нужен edge serverless с нулевым холодным стартом, обратите внимание на Cloudflare Workers и Vercel Edge Functions.
Cloudflare Workers + Rust через WASM
Cloudflare Workers не поддерживают нативные бинарники, но отлично работают с WebAssembly (WASM). Rust компилируется в WASM, который выполняется на V8 изолятах Cloudflare.
// worker/src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn handle_request(name: &str) -> String {
format!("Привет, {}! Ответ из Cloudflare Worker на Rust!", name)
}
Плюсы: холодный старт < 5 мс, глобальная сеть, бесплатный лимит 100k запросов/день. Минусы: ограничения WASM (нет доступа к файловой системе, syscalls).
Vercel Edge Functions + Rust
Vercel поддерживает Rust через wasm-pack. Собираете WASM-модуль и подключаете его к Edge Function. Это идеально для API-геев, которые хотят скорость Rust на edge.
// api/hello.rs (Vercel Edge)
use vercel_runtime::{run, Body, Error, Request, Response, StatusCode};
#[tokio::main]
async fn main() -> Result<(), Error> {
run(handler).await
}
async fn handler(_req: Request) -> Result<Response<Body>, Error> {
Ok(Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "application/json")
.body(Body::Text(r#"{"message": "Hello from Rust on Vercel!"}"#.into()))?)
}
Бенчмарки: Rust vs Python в Serverless
Мы прогнали тест: 1000 последовательных запросов к AWS Lambda с минимальной функцией (возврат JSON). Результаты:
| Метрика | Python 3.12 | Rust (cargo-lambda) |
|---|---|---|
| Холодный старт (p50) | 620 ms | 85 ms |
| Холодный старт (p99) | 1.2 s | 180 ms |
| Время выполнения (тёплый) | 12 ms | 0.4 ms |