🏗️🧠 Serverless & FaaS: chạy code không cần server, nhưng có nên dùng? - System Design P30
Serverless & FaaS: Khi "Không Máy Chủ" Trở Thành Gánh Nặng Vận Hành
1. Dẫn nhập: Câu chuyện từ thực tế sản xuất
Cách đây hai năm, tôi từng tham gia tư vấn cho một startup trong lĩnh vực Fintech đang ở giai đoạn tăng trưởng nóng. Để giải quyết bài toán "Go-to-market" thần tốc, đội ngũ kỹ sư—với tâm thế của những người tôn sùng sự hiện đại—đã quyết định đặt cược 100% vào kiến trúc Serverless, cụ thể là AWS Lambda.
Bầu không khí lúc đó rất hưng phấn. Các kỹ sư trẻ khoe với tôi rằng họ không còn phải cấu hình Nginx, không lo patching hệ điều hành, cũng chẳng cần thức đêm để thiết lập auto-scaling group. "Chỉ cần viết code, đẩy lên và Cloud sẽ lo phần còn lại," họ nói. Đúng là trong giai đoạn MVP (Minimum Viable Product), Serverless đã thực sự tỏa sáng. Họ ra mắt tính năng mới mỗi tuần, chi phí vận hành ban đầu gần như bằng không.
Nhưng "tuần trăng mật" kết thúc khi hệ thống chạm ngưỡng 10.000 người dùng đồng thời (concurrent users).
Một đêm thứ Bảy, hệ thống thanh toán gặp sự cố. Khách hàng phàn nàn rằng ứng dụng bị "treo" ở màn hình xác nhận. Khi đội ngũ kỹ sư nhảy vào debug, họ rơi vào một mê cung thực sự. Latency P99 nhảy vọt từ 200ms lên tận 6 giây mà không rõ nguyên nhân. Log từ CloudWatch rời rạc, việc tracing một request đi qua chuỗi 15 function khác nhau trở thành một nhiệm vụ bất khả thi trong môi trường production đang "cháy".
Tệ hơn nữa, khi cố gắng tái lập lỗi ở môi trường local, họ nhận ra rằng việc giả lập các trigger từ S3, DynamoDB Streams và SQS trên máy cá nhân là một cơn ác mộng về mặt tính nhất quán. Đó là khoảnh khắc họ nhận ra: Serverless không hề làm "biến mất" máy chủ; nó chỉ ẩn đi sự phức tạp của hạ tầng để rồi trả lại cho bạn một gánh nặng vận hành khác, tinh vi và khó kiểm soát hơn gấp bội.
2. Niềm tin phổ biến vs. Thực tế phũ phàng
Trong cộng đồng kỹ thuật, có những niềm tin về Serverless đã được "marketing hóa" đến mức trở thành định kiến. Dưới lăng kính của một Senior Architect, chúng ta cần bóc tách những ảo tưởng này dựa trên các giới hạn vật lý và kinh tế thực tế.
Niềm tin 1: Serverless nghĩa là không còn phải nghĩ về hạ tầng.Thực tế: Hạ tầng chỉ bị ẩn đi (abstracted away). Các giới hạn vật lý của nó như Resource Contention (tranh chấp tài nguyên), Network I/O, và CPU Throttling vẫn tồn tại. Trong FaaS, bạn thường không được chọn dòng CPU hay tốc độ ổ cứng. Bạn bị bó buộc vào các "Execution Context" mà nhà cung cấp Cloud quy định. Khi một function chạy chậm, bạn không thể SSH vào để xem top hay iostat. Bạn trở thành "con tin" của Platform.
Niềm tin 2: Serverless luôn rẻ hơn.Thực tế: Mô hình "Pay-as-you-go" chỉ rẻ khi workload của bạn có đặc tính "spiky" (biến thiên lớn) hoặc thấp. Khi hệ thống đạt đến một ngưỡng throughput ổn định và cao, chi phí biên (marginal cost) của Serverless bắt đầu bóp nghẹt lợi nhuận. Nếu so sánh chi phí trên mỗi triệu request, một cụm Kubernetes chạy trên Spot Instances thường rẻ hơn AWS Lambda từ 3 đến 5 lần ở cùng một mức tải. Chi phí thực sự của Serverless còn bao gồm cả "Complexity Debt" — số giờ kỹ sư tiêu tốn để tối ưu hóa cold start và debug các lỗi phân tán.
Niềm tin 3: FaaS phù hợp cho mọi loại backend.Thực tế: FaaS được thiết kế cho các tác vụ stateless và ngắn hạn. Nếu bạn cố gắng đưa một logic nghiệp vụ phức tạp, đòi hỏi duy trì kết nối database lâu dài (long-lived connections) hoặc các tác vụ tính toán nặng (heavy compute), bạn đang đi ngược lại bản chất của công nghệ. FaaS chỉ tối ưu cho một số mẫu truy cập (access patterns) nhất định như xử lý sự kiện hoặc các API đơn giản.
3. Bản chất của Serverless trong System Design
Tại sao Serverless tồn tại? Nếu gạt bỏ những hào nhoáng bên ngoài, Serverless là một Architectural Decision dựa trên sự đánh đổi: Bạn đổi quyền kiểm soát (Control) lấy vận tốc (Velocity) và khả năng tập trung vào logic nghiệp vụ.
Trong hành trình tiến hóa của hệ thống (Stage 5 - Evolution), Serverless thường xuất hiện sau khi chúng ta đã thực hiện Read/Write Splitting hoặc CQRS. Đây là một nỗ lực để "offload" gánh nặng của Stage 6 (Platform Thinking/Autoscaling) ngược lại cho Cloud Provider. Tuy nhiên, một kiến trúc sư hệ thống phải hiểu rằng: Ẩn bớt server không có nghĩa là ẩn bớt sự phức tạp; complexity chỉ chuyển từ việc quản lý máy chủ sang quản lý luồng dữ liệu (data flow), observability và các giới hạn của platform.
Thay vì lo lắng về việc patch Linux kernel, giờ đây bạn phải lo lắng về việc làm sao để 50 functions khác nhau không vượt quá giới hạn "Regional Concurrency Limit". Sự phức tạp không biến mất, nó chỉ đổi hình hài từ "Infrastructure Complexity" sang "Architecture & Integration Complexity".
4. Phân tích kỹ thuật: Những "Cái giá" tiềm ẩn
Để tư duy như một Senior Engineer, chúng ta cần thực hiện Root Cause Analysis (phân tích nguyên nhân gốc rễ) cho những vấn đề của Serverless.
Cold Start: Kẻ thù của Latency-Sensitive
Cold Start xảy ra khi Cloud Provider phải khởi tạo một container runtime mới, tải code và khởi động môi trường thực thi vì không có instance nào đang sẵn sàng.
- Tác động: Đây là một "latency spike" khó dự đoán. Đối với các runtime nặng như Java (Spring Boot) hoặc .NET, Cold Start có thể mất từ 2-5 giây. Thậm chí với Go hay Node.js, nó vẫn tốn vài trăm milisecond.
- Blast Radius: Trong một kiến trúc Microservices, nếu Request A gọi Function B, B gọi C, và tất cả đều gặp Cold Start cùng lúc, latency sẽ tích lũy theo cấp số cộng. Kết quả là người dùng cuối sẽ thấy một màn hình trắng xóa. Giải pháp "Provisioned Concurrency" của AWS thực chất là trả tiền để giữ server luôn nóng—về cơ bản là quay lại mô hình "Serverful" nhưng với cái giá đắt hơn.
Sự đứt gãy của Observability
Trong môi trường truyền thống, chúng ta có các Agent (như NewRelic hoặc Datadog) chạy dưới dạng daemon hoặc sidecar để thu thập metrics liên tục. Trong FaaS, môi trường thực thi là "ephemeral" (tạm thời). Container sẽ bị đóng băng (freeze) ngay sau khi request kết thúc.
- Hậu quả: Bạn không thể gửi metrics theo cách truyền thống vì nó sẽ làm tăng latency của request (phải đợi gửi xong mới đóng container). Việc tracing một request qua nhiều function đòi hỏi phải cài đặt các thư viện phức tạp hơn và chấp nhận overhead về network. Hệ thống của bạn dễ dàng trở thành một "hộp đen" nơi bạn thấy lỗi nhưng không biết nó bắt đầu từ mắt xích nào.
Vendor Lock-in và Platform Limits
Serverless không chỉ là code; nó là sự tích hợp sâu với các dịch vụ của nhà cung cấp Cloud (S3, DynamoDB, EventBridge).
- Rủi ro: Khi bạn viết code gắn chặt với API của Lambda, việc chuyển đổi sang Google Cloud Functions hay quay về on-premise là cực kỳ tốn kém. Ngoài ra, mỗi Platform đều có các giới hạn cứng (Hard Limits) như: dung lượng gói code (deployment package size), timeout tối đa (thường là 15 phút), và giới hạn bộ nhớ. Khi hệ thống của bạn vượt quá các giới hạn này, bạn buộc phải đập đi xây lại kiến trúc thay vì chỉ đơn giản là nâng cấp RAM.
5. Ma trận đánh đổi (Trade-off Analysis)
Dưới đây là bảng phân tích đối sánh chi tiết dưới góc nhìn kiến trúc:
| Tiêu chí | Serverless (FaaS) | Server-based / Kubernetes |
|---|---|---|
| Năng suất đầu (Productivity) | Cực cao. Deploy code trong vài phút. | Thấp. Cần setup CI/CD, K8s, Ingress. |
| Quản lý vận hành (Ops) | Giảm tải quản lý OS/Patching. Tăng tải quản lý Platform limits & IaC. | Phải quản lý toàn bộ stack. Cần đội ngũ DevOps chuyên nghiệp. |
| Chi phí (Cost Model) | Pay-as-you-go. Tiết kiệm khi tải thấp. | Chi phí cố định cao. Tiết kiệm khi tải cao và ổn định. |
| Khả năng kiểm soát | Thấp. "Black-box" runtime. | Cao. Có thể tối ưu ở mức Kernel/Network. |
| Trạng thái (State) | Stateless by design. Khó quản lý DB connection pool. | Có thể chạy cả Stateful & Stateless. Dễ tối ưu connection pooling. |
| Bảo mật (Security) | Shared responsibility ở mức cao. Cách ly tốt. | Bạn tự chịu trách nhiệm bảo mật OS và Network. |
6. Những trường hợp thất bại điển hình
Tôi đã từng chứng kiến nhiều đội ngũ kỹ sư phải trả giá đắt khi chọn Serverless sai ngữ cảnh:
**Trường hợp 1: Tác vụ xử lý dữ liệu nặng (Heavy Processing)**Một startup xử lý video dùng Lambda để transcode clip từ người dùng. Vì giới hạn timeout 15 phút, họ phải chia nhỏ video thành hàng nghìn đoạn ngắn, mỗi đoạn gọi một Lambda riêng, sau đó dùng một Lambda khác để ghép lại. Kết quả: Chi phí Network I/O và chi phí gọi function chồng chéo khiến hóa đơn Cloud tăng 400% so với việc chạy một cụm Worker Node trên EC2. Đây là minh chứng cho việc chi phí biên của Serverless sẽ "ăn thịt" lợi nhuận khi scale.
**Trường hợp 2: Microservices quá vụn vặt (Nanoservices)**Một team khác chia logic nghiệp vụ thành quá nhiều function nhỏ (ví dụ: get-user-name, get-user-address là 2 function riêng). Khi cần hiển thị profile người dùng, ứng dụng phải thực hiện 5-6 lượt gọi function qua lại trên network. Độ trễ tích lũy (Cumulative Latency) do Network Overhead và Cold Start khiến ứng dụng chậm chạp đến mức không thể sử dụng, dù từng function đơn lẻ chạy rất nhanh.
7. Tư duy Senior: Khi nào Serverless thực sự tỏa sáng?
Đừng hiểu lầm rằng tôi đang bài trừ Serverless. Là một kiến trúc sư, tôi coi Serverless là một mũi tên sắc bén trong ống tên của mình, miễn là nó được dùng đúng mục đích:
- Event-driven processing: Đây là "vùng đất hứa" của Serverless. Xử lý ảnh ngay khi upload lên S3, xử lý Webhook từ Stripe/PayPal, hoặc tiêu thụ tin nhắn từ Queue (SQS/Kafka).
- Tác vụ không thường xuyên (Cron jobs): Thay vì duy trì một server 24/7 chỉ để chạy script dọn dẹp database lúc 2 giờ sáng, hãy dùng một Scheduled Lambda. Tiết kiệm 100% chi phí nhàn rỗi.
- MVP và Validation: Khi bạn cần chứng minh ý tưởng kinh doanh và chưa biết liệu có 10 hay 1.000.000 user. Tốc độ đưa tính năng ra thị trường lúc này quan trọng hơn chi phí vận hành lâu dài.
- Hệ thống có lưu lượng biến thiên cực lớn: Ví dụ trang web bán vé concert bùng nổ traffic trong 30 phút rồi "im hơi lặng tiếng" cả tháng. Khả năng scale từ 0 lên 10.000 instance của Serverless là vô địch trong trường hợp này.
8. Kết luận và Bài học kinh nghiệm
Serverless không phải là một phép màu giúp bạn thoát khỏi gánh nặng kỹ thuật; nó là một sự lựa chọn kinh doanh dựa trên rủi ro và chi phí.
- Thứ nhất: Hãy chọn Serverless dựa trên đặc tính của workload, đừng chọn vì nó là xu hướng.
- Thứ hai: Nếu bạn không thể quản lý một server, bạn chắc chắn không thể quản lý một ngàn function. Đừng dùng Serverless để trốn tránh trách nhiệm hiểu về hạ tầng.
- Thứ ba: Luôn có chiến lược thoát hiểm (Exit Strategy). Hãy viết code sao cho logic nghiệp vụ tách biệt hoàn toàn với API của Provider, để khi cần, bạn có thể đóng gói chúng vào một container Docker và chạy trên Kubernetes mà không phải sửa đổi quá nhiều.
9. Mở rộng tư duy & Kết nối
Nếu Serverless giúp chúng ta ẩn đi hạ tầng để tập trung vào mã nguồn, thì một vấn đề mới lại nảy sinh: Làm thế nào để chúng ta quản lý hàng trăm function, hàng ngàn trigger và vô số các IAM policy đó một cách nhất quán mà không bị lạc lối trong mớ hỗn độn của Cloud Console?
Câu trả lời không phải là "ít server hơn", mà là "tự động hóa tốt hơn". Chúng ta sẽ cùng giải mã bài toán này trong bài viết tiếp theo: Episode 31 - Infrastructure as Code (IaC): Quản Lý Hạ Tầng Bằng Code, Không Bằng Tay.
Tại TechCraft, chúng tôi không dạy bạn cách dùng công cụ, chúng tôi giúp bạn rèn luyện tư duy để biết tại sao và khi nào nên dùng chúng. Nếu bạn muốn đi sâu hơn vào các bài toán đánh đổi trong thiết kế hệ thống thực thụ, hãy theo dõi chuỗi System Design Series của chúng tôi trên Viblo.
Nội dung này thuộc bản quyền của TechCraft - Nơi chia sẻ tư duy kỹ thuật chuyên sâu cho cộng đồng kỹ sư thực chiến.
🚀 Tiếp tục hành trình cùng TechCraft
Bài viết này là một phần trong hành trình khám phá Backend Engineering, System Design và Production Systems tại TechCraft.
Nếu bạn muốn học theo một lộ trình rõ ràng hơn, TechCraft đang xây dựng Dev Insider như nơi tập trung các series chuyên sâu hơn về:
- Backend Internals
- Database Internals
- Transaction & Consistency
- Distributed Systems
- Production System Design
- AI-Proof Engineer
🚀 Dev Insider
https://www.patreon.com/techcraft_official/posts/vi-sao-dev-ra-161163881?collection=2220113
📘 Facebook
https://www.facebook.com/techcraft.official
🎥 YouTube
https://www.youtube.com/@techcraft.official
🎵 TikTok
https://www.tiktok.com/@techcraft.official
Hiểu hệ thống. Không chỉ framework.
All Rights Reserved