•12 min read

Những cạm bẫy tiềm ẩn của kiến trúc Serverless

Những cạm bẫy tiềm ẩn của kiến trúc Serverless

Điện toán phi máy chủ (serverless computing)—được tiên phong bởi AWS Lambda, Google Cloud Functions và Cloudflare Workers—hứa hẹn một thiên đường kỹ thuật: không cần quản trị hệ điều hành, khả năng mở rộng vô hạn mà không cần can thiệp thủ công, và mô hình thanh toán giảm về 0 khi lưu lượng truy cập giảm.

Đối với xử lý bất đồng bộ theo sự kiện và xử lý webhook không thường xuyên, serverless mang tính đột phá.

Tuy nhiên, khi hàng ngàn đội ngũ kỹ sư đã di chuyển khối lượng công việc doanh nghiệp sang serverless trong thập kỷ qua, nhiều người đã gặp phải một loạt các cạm bẫy kiến trúc phức tạp mà các tài liệu quảng cáo của nhà cung cấp hiếm khi đề cập.

Từ các cơn bão kết nối cơ sở dữ liệu quan hệ thảm khốc đến các vòng lặp thanh toán đệ quy làm cạn kiệt ngân sách công ty chỉ sau một đêm, hướng dẫn này khám phá thực tế của việc vận hành kiến trúc serverless vào năm 2026 và cung cấp các mẫu đã được thử nghiệm trong thực tế để tránh chúng.


Audio Briefing
0:00 / 0:00

1. Chi phí thực sự của Cold Start: Vật lý so với Lời hứa

Khi một hàm serverless được gọi sau một thời gian không hoạt động, hypervisor đám mây phải thực hiện một chuỗi các bước khởi tạo trước khi xử lý một dòng mã người dùng:

  1. Cấp phát phân đoạn tính toán (microVM Firecracker trong AWS Lambda).
  2. Tải xuống các lớp container hoặc kho lưu trữ zip từ S3/ECR.
  3. Khởi động runtime ngôn ngữ (Node.js, Python, Java JVM).
  4. Thực thi logic khởi tạo phạm vi toàn cục (thiết lập kết nối cơ sở dữ liệu, nhập các thư viện nặng).

Chi phí khởi tạo này chính là Cold Start.

[ Cold Start Sequence (500ms - 3,500ms) ]
┌─────────────────┬───────────────────┬─────────────────┬─────────────────┐
│ Firecracker VM  │ Runtime Boot      │ Global Imports  │ Handler Execute │
│ (50 - 150ms)    │ (100 - 400ms)     │ (300 - 3000ms)  │ (10 - 50ms)     │
└─────────────────┴───────────────────┴─────────────────┴─────────────────┘

Mặc dù một cold start 1,5 giây là chấp nhận được đối với một worker hàng đợi SQS bất đồng bộ, nhưng nó gây ra độ trễ đuôi (p99) không thể chấp nhận được trên các API HTTP hướng người dùng.

Các chiến lược giảm thiểu trong sản xuất

  • Giữ phạm vi toàn cục tối thiểu: Tránh nhập toàn bộ SDK (import * as AWS from 'aws-sdk'). Nhập các module client riêng lẻ một cách động hoặc loại bỏ các dependency không cần thiết trong quá trình build bằng cách sử dụng esbuild.
  • Áp dụng các runtime biên dịch, tối thiểu: Các ngôn ngữ biên dịch như Go và Rust trên các runtime tùy chỉnh của AWS Lambda (provided.al2023) tự hào có thời gian cold start dưới 25ms, so với 300–800ms cho Python/Node.js, và 2.000ms+ cho các runtime JVM cũ.
  • AWS Lambda SnapStart: Đối với các khối lượng công việc Java và Python, SnapStart khởi tạo microVM tại thời điểm triển khai, tạo một ảnh chụp bộ nhớ được mã hóa và khôi phục trạng thái thực thi trong vòng dưới 100ms.
  • Provisioned Concurrency: Giữ một nhóm môi trường thực thi được cấp phát trước và khởi tạo sẵn. Đánh đổi: Provisioned Concurrency được tính phí liên tục theo giờ, làm mất đi lợi thế kinh tế "scale-to-zero" của serverless.

Advertisement

2. Cơn ác mộng về kết nối cơ sở dữ liệu

Các công cụ cơ sở dữ liệu quan hệ truyền thống (PostgreSQL, MySQL) được kiến trúc dựa trên giả định về các kết nối trạng thái tồn tại lâu dài. Một nhóm máy chủ ứng dụng (ví dụ: 4 phiên bản Django hoặc Spring Boot) duy trì 40 kết nối TCP liên tục trong nhiều ngày hoặc nhiều tuần.

Serverless hoàn toàn đảo ngược mô hình này. Bởi vì mỗi lần gọi đồng thời chạy trong một microVM riêng biệt, một đợt tăng đột biến lưu lượng truy cập 2.000 yêu cầu đồng thời sẽ tạo ra 2.000 môi trường thực thi Lambda độc lập.

Nếu mỗi môi trường mở một kết nối đến PostgreSQL, cơ sở dữ liệu ngay lập tức nhận được 2.000 lần bắt tay TCP đồng thời:

[ 2,000 Concurrent Lambdas ]
    │   │   │   │   │
    ▼   ▼   ▼   ▼   ▼   (2,000 Simultaneous TCP Connections!)
┌─────────────────────────┐
│   PostgreSQL Instance   │  --> MAX CONNECTIONS EXCEEDED (500)
│   (Max Connections: 500)│  --> CRASH / DEADLOCK / CASCADING TIMEOUTS!
└─────────────────────────┘

Máy chủ cơ sở dữ liệu bị cạn kiệt CPU do phân nhánh tiến trình backend, cạn kiệt các bộ mô tả tệp có sẵn và gặp sự cố, làm sập toàn bộ hệ thống.

Cách khắc phục: Ghép kênh kết nối & API dữ liệu HTTP

[ 2,000 Ephemeral Lambdas ]
              │ (HTTP / Fast TCP Multiplexing)
              ▼
    ┌───────────────────┐
    │  AWS RDS Proxy /  │  --> Maintains a steady pool of 50 long-lived
    │    PgBouncer      │      database connections to Postgres
    └─────────┬─────────┘
              │ (50 Stable Connections)
              ▼
    ┌───────────────────┐
    │  PostgreSQL DB    │  --> Operates smoothly at 15% CPU load
    └───────────────────┘
  1. Triển khai một bộ điều phối kết nối chuyên dụng: Đặt AWS RDS Proxy hoặc PgBouncer phía trước cơ sở dữ liệu của bạn. Proxy giữ một nhóm kết nối cơ sở dữ liệu cố định và ghép kênh hàng ngàn truy vấn Lambda tạm thời qua chúng.
  2. Áp dụng các cơ sở dữ liệu Serverless không kết nối: Đối với các khối lượng công việc serverless gốc, chuyển sang các cơ sở dữ liệu được thiết kế cho vận chuyển HTTP không trạng thái, chẳng hạn như Neon (Postgres serverless với nhóm WebSocket/HTTP), PlanetScale hoặc DynamoDB.

3. Cơn bão thanh toán đệ quy: Bẫy vòng lặp vô hạn

Trong hạ tầng dựa trên máy chủ, một lỗi logic tạo ra vòng lặp vô hạn sẽ khiến CPU máy chủ đạt 100%. Tiến trình gặp sự cố, hệ thống giám sát cảnh báo và hóa đơn đám mây của bạn vẫn không thay đổi.

Trong môi trường serverless, các nhà cung cấp đám mây tự động mở rộng dung lượng tính toán để phù hợp với nhu cầu gọi. Nếu một vòng lặp đệ quy được đưa vào, hạ tầng đám mây của bạn sẽ mở rộng mạnh mẽ lên hàng chục nghìn phiên bản:

┌─────────────────┐        1. Message Put        ┌─────────────────┐
│   S3 / DynamoDB │ ───────────────────────────> │  Lambda Handler │
└─────────────────┘                              └────────┬────────┘
         ▲                                                │
         │             2. Writes Object / Error           │
         └────────────────────────────────────────────────┘
                 (Infinite Exponential Trigger Storm!)

Kịch bản lỗi thực tế

  1. Một hình ảnh được tải lên một S3 bucket, kích hoạt một hàm Lambda để thay đổi kích thước hình thu nhỏ.
  2. Hàm Lambda lưu hình thu nhỏ đã thay đổi kích thước trở lại vào cùng S3 bucket đó.
  3. Hình thu nhỏ mới được lưu lại kích hoạt hàm Lambda một lần nữa.
  4. Trong vòng 30 phút, 500.000 Lambda chạy đồng thời, tạo ra hàng nghìn đô la chi phí S3 và Lambda.

Các biện pháp phòng thủ ngắt mạch thiết yếu

# AWS SAM / CloudFormation Circuit Breaker
Resources:
  ImageProcessorFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs20.x
      # 1. Hard Concurrency Ceiling (Financial Circuit Breaker)
      ReservedConcurrentExecutions: 50
      # 2. Strict Timeout Protection
      Timeout: 10
  • Giới hạn đồng thời dự trữ: Luôn chỉ định ReservedConcurrentExecutions trên mỗi hàm. Điều này thiết lập một giới hạn tuyệt đối về số lượng thực thi đồng thời, ngăn chặn chi tiêu vượt tầm kiểm soát.
  • Tách biệt các bucket Ingress và Egress: Các trình kích hoạt sự kiện không bao giờ được ghi đầu ra trở lại đường dẫn sự kiện nguồn của chúng.
  • Cảnh báo thanh toán CloudWatch theo cấp độ: Cấu hình cảnh báo gửi SMS và PagerDuty ở mức 50%, 100% và 200% chi tiêu hàng ngày dự kiến.

4. Độ phức tạp kiến trúc: Chống mẫu "Lambda-Pin"

Khi các tổ chức chia một ứng dụng thành 150 hàm đơn mục đích chi tiết (ví dụ: getUser, updateUserEmail, deleteUserCart), độ phức tạp không biến mất—nó chuyển sang cấu hình mạng và các pipeline triển khai.

  • Gỡ lỗi cục bộ trở nên khó khăn: Chạy 40 hàm liên kết cục bộ với các mock cho EventBridge, SQS, DynamoDB và Cognito yêu cầu các trình giả lập nặng (LocalStack) thường xuyên khác biệt so với hành vi AWS thực tế.
  • Theo dõi phân tán là bắt buộc: Hiểu tại sao một đơn hàng thất bại yêu cầu theo dõi các yêu cầu trên 6 hàng đợi bất đồng bộ và 8 Lambda bằng AWS X-Ray hoặc OpenTelemetry.

Sự thỏa hiệp hiện đại: "Lambda-lith"

Thay vì triển khai 50 hàm chi tiết cho một API, các nhóm hiện đại triển khai một Lambda-lith sử dụng Fastify, Express hoặc FastAPI được gói trong một bộ điều hợp (chẳng hạn như @codegenie/serverless-express hoặc mangum):

# main.py (FastAPI Lambda-lith)
from fastapi import FastAPI
from mangum import Mangum

app = FastAPI()

@app.get("/api/v1/users")
def get_users():
    return [{"id": 1, "name": "Loc"}]

@app.post("/api/v1/users")
def create_user():
    return {"status": "created"}

# Single entry point for AWS Lambda
handler = Mangum(app)

Tại sao Lambda-lith thắng thế đối với các nhóm nhỏ đến trung bình:

  1. Bạn có thể chạy uvicorn main:app --reload cục bộ để có phản hồi phát triển tức thì mà không cần Docker hoặc trình giả lập AWS.
  2. Định tuyến được xử lý trong tiến trình, loại bỏ cấu hình định tuyến trên mỗi tuyến của API Gateway.
  3. Hàm luôn ở trạng thái nóng vì tất cả các điểm cuối API chia sẻ cùng một nhóm microVM.

Advertisement

Serverless so với Container: Ma trận quyết định

Đặc điểm khối lượng công việcServerless (AWS Lambda)Container (ECS / Kubernetes)
Hồ sơ lưu lượng truy cậpĐột biến, không thể đoán trước, không thường xuyênNhất quán, có thể dự đoán, trạng thái ổn định
Tính toán chạy dài (> 15 phút)❌ Giới hạn thực thi cứng 15 phút✅ Chạy vô thời hạn
WebSockets / TCP liên tục⚠️ Yêu cầu API Gateway WebSockets✅ Socket liên tục gốc, chi phí thấp
Chi phí ở 1.000 RPS liên tục⚠️ Cao (Tính phí theo ms và GB-s)✅ Rẻ hơn đáng kể trên mỗi đơn vị tính toán
Độ nhạy Cold Start⚠️ Yêu cầu SnapStart / Warming✅ Không có cold start (luôn chạy)
Bảo trì vận hành⭐ Không có chi phí OS / vá lỗi⚠️ Nâng cấp Node, vá lỗi bảo mật

Câu hỏi thường gặp

Đối với lưu lượng truy cập thấp đến trung bình hoặc đột biến, serverless rẻ hơn đáng kể vì bạn không phải trả gì khi không hoạt động. Tuy nhiên, một khi một dịch vụ xử lý lưu lượng truy cập cao, ổn định (ví dụ: duy trì 500+ yêu cầu mỗi giây 24/7), chạy container trên ECS Fargate hoặc Kubernetes với các phiên bản Spot thường rẻ hơn 60% đến 80% so với AWS Lambda.

Không gọi AWS Secrets Manager hoặc HashiCorp Vault trong mỗi lần gọi. Lấy bí mật trong phạm vi toàn cục trong quá trình cold start và lưu trữ chúng trong bộ nhớ với Time-To-Live (TTL) bằng cách sử dụng AWS Parameters and Secrets Lambda Extension.

Không. Ngay khi một hàm serverless trả về phản hồi HTTP, hypervisor đám mây sẽ đóng băng chu kỳ CPU của microVM cho đến lần gọi tiếp theo. Các luồng nền hoặc bộ hẹn giờ setInterval bị tạm dừng ngay lập tức. Sử dụng các hàng đợi bên ngoài (như SQS hoặc Celery) để xử lý nền.


Kết luận

Serverless không phải là một đề xuất tất cả hoặc không có gì. Các kiến trúc kiên cường nhất vào năm 2026 là kiến trúc lai: các microservice trạng thái ổn định được container hóa cho các API khối lượng lớn và WebSockets liên tục, kết hợp với các hàm serverless để xử lý tệp theo sự kiện, nhập webhook và các tác vụ cron đột biến.

Bằng cách thiết kế cho cold start, nhóm các kết nối cơ sở dữ liệu thông qua proxy và thiết lập các bộ ngắt mạch đồng thời nghiêm ngặt, bạn có thể nắm bắt sự linh hoạt của serverless mà không rơi vào các cạm bẫy vận hành của nó.


Bạn cũng có thể thích

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement
Chạy nước rút đám mây 13 ngày: Biến tín dụng GCP sắp hết hạn thành tài sản vĩnh viễn không cần bảo trì
cloud

Chạy nước rút đám mây 13 ngày: Biến tín dụng GCP sắp hết hạn thành tài sản vĩnh viễn không cần bảo trì

Hướng dẫn thực tế để tối đa hóa ROI từ các khoản tín dụng Google Cloud sắp hết hạn, giúp bạn chuyển đổi tài nguyên điện toán tạm thời thành nội dung SEO vĩnh viễn, âm thanh thần kinh và tập dữ liệu được tính toán trước với chi phí sau khi hết hạn bằng không.

Read more