Giao diện
Rust in the Cloud Cloud Native
Serverless và Containers — Tận dụng tối đa performance của Rust trong môi trường Cloud
Tại sao Rust cho Cloud?
┌─────────────────────────────────────────────────────────────────────┐
│ CLOUD PERFORMANCE COMPARISON │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Metric │ Java/Node.js │ Go │ Rust │
│ ────────────────┼──────────────────┼───────────────┼───────────── │
│ Cold Start │ 2-5 seconds │ 200-500ms │ 50-100ms │
│ Memory Usage │ 256-512MB │ 50-100MB │ 10-30MB │
│ Binary Size │ 50-200MB │ 10-20MB │ 2-8MB │
│ Throughput │ Baseline │ 5-10x │ 10-20x │
│ │
│ Chi phí Lambda │ $$$$$ │ $$ │ $ │
│ (per 1M req) │ │ │ │
└─────────────────────────────────────────────────────────────────────┘1. AWS Lambda với Rust
Setup với cargo-lambda
bash
# Install cargo-lambda
cargo install cargo-lambda
# Tạo project mới
cargo lambda new my-lambda-function
cd my-lambda-functionHandler cơ bản
rust
// src/main.rs
use lambda_runtime::{service_fn, LambdaEvent, Error};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Request {
name: String,
}
#[derive(Serialize)]
struct Response {
message: String,
}
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
let name = &event.payload.name;
Ok(Response {
message: format!("Hello, {}!", name),
})
}
#[tokio::main]
async fn main() -> Result<(), Error> {
lambda_runtime::run(service_fn(handler)).await
}Cargo.toml
toml
[package]
name = "my-lambda-function"
version = "0.1.0"
edition = "2021"
[dependencies]
lambda_runtime = "0.8"
tokio = { version = "1", features = ["macros"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# Optimize for size
[profile.release]
opt-level = "z" # Optimize for size
lto = true # Link-time optimization
codegen-units = 1 # Better optimization
panic = "abort" # Smaller binary
strip = true # Strip symbolsBuild và Deploy
bash
# Build cho Amazon Linux 2 (ARM64 - Graviton)
cargo lambda build --release --arm64
# Hoặc x86_64
cargo lambda build --release
# Deploy trực tiếp
cargo lambda deploy --iam-role arn:aws:iam::ACCOUNT:role/LambdaRole
# Test locally
cargo lambda watch
cargo lambda invoke --data-ascii '{"name": "World"}'Tối ưu Cold Start
rust
// 1. Lazy initialization với OnceCell
use std::sync::OnceLock;
use aws_sdk_dynamodb::Client;
static DB_CLIENT: OnceLock<Client> = OnceLock::new();
fn get_db_client() -> &'static Client {
DB_CLIENT.get_or_init(|| {
let config = aws_config::load_from_env().await;
Client::new(&config)
})
}
// 2. Warm up connections trong init phase
// Lambda runtime tự động gọi init trước handler đầu tiên2. Multi-Stage Docker với musl (Alpine)
Goal: Tạo static binary < 10MB có thể chạy trên bất kỳ Linux container nào.
Dockerfile tối ưu
dockerfile
# Stage 1: Build
FROM rust:1.75-alpine AS builder
# Install build dependencies
RUN apk add --no-cache musl-dev openssl-dev openssl-libs-static pkgconfig
WORKDIR /app
# Cache dependencies
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release && rm -rf src
# Build actual app
COPY src ./src
RUN touch src/main.rs # Force rebuild
RUN cargo build --release --target x86_64-unknown-linux-musl
# Strip binary
RUN strip /app/target/x86_64-unknown-linux-musl/release/myapp
# Stage 2: Runtime (scratch or distroless)
FROM scratch
# Copy CA certificates for HTTPS
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Copy binary
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/myapp /myapp
# Run as non-root
USER 1000:1000
ENTRYPOINT ["/myapp"]Kết quả
bash
$ docker images myapp
REPOSITORY TAG SIZE
myapp latest 5.2MB # vs 200MB+ cho Java/Node
$ docker run myapp
# Starts in ~10ms vs seconds for JVMCross-compile từ macOS/Windows
bash
# Install musl target
rustup target add x86_64-unknown-linux-musl
# Install cross-compilation toolchain
# macOS:
brew install FiloSottile/musl-cross/musl-cross
# Build
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-musl-gcc \
cargo build --release --target x86_64-unknown-linux-musl3. OpenSSL Static Linking
Vấn đề: OpenSSL thường là dynamic library → container cần có lib.
Option A: rustls (Pure Rust TLS)
toml
# Cargo.toml - Dùng rustls thay OpenSSL
[dependencies]
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] }Option B: OpenSSL Static
toml
# Cargo.toml
[dependencies]
openssl = { version = "0.10", features = ["vendored"] }dockerfile
# Dockerfile - Alpine với static OpenSSL
RUN apk add --no-cache openssl-libs-static4. Docker Compose cho Development
yaml
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/myapp
- RUST_LOG=info
depends_on:
- db
- redis
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: myapp
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
postgres_data:5. Health Checks & Kubernetes Ready
rust
// Axum health check endpoint
use axum::{Router, Json, routing::get};
use serde::Serialize;
#[derive(Serialize)]
struct HealthResponse {
status: &'static str,
version: &'static str,
}
async fn health() -> Json<HealthResponse> {
Json(HealthResponse {
status: "healthy",
version: env!("CARGO_PKG_VERSION"),
})
}
async fn ready() -> &'static str {
// Check DB connection, etc.
"ready"
}
fn app() -> Router {
Router::new()
.route("/health", get(health)) // Liveness probe
.route("/ready", get(ready)) // Readiness probe
// ... other routes
}Kubernetes Deployment
yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: rust-app
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: myrepo/rust-app:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "32Mi" # Rust cần rất ít RAM
cpu: "50m"
limits:
memory: "64Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 1 # Rust khởi động nhanh
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 1
periodSeconds: 5Bảng Tóm tắt
| Scenario | Best Practice |
|---|---|
| AWS Lambda | cargo-lambda, ARM64 Graviton, cold start < 100ms |
| Docker | Multi-stage build, musl, scratch/distroless base |
| TLS | rustls (pure Rust) hoặc vendored OpenSSL |
| Binary Size | opt-level = "z", LTO, strip, panic = "abort" |
| Kubernetes | 32MB memory limit, 1s initialDelaySeconds |