Bỏ qua để đến nội dung

Kiến trúc Serverless mẫu

Chương này không giới thiệu dịch vụ mới — nó ghép các dịch vụ đã học thành kiến trúc, và đó cũng chính là dạng câu hỏi tình huống của đề thi. Bài toán đầu tiên là một ứng dụng mobile với các yêu cầu sau:

  • Phơi ra dưới dạng REST API với HTTPS.
  • Kiến trúc serverless.
  • Người dùng phải tương tác trực tiếp với thư mục riêng của mình trong S3.
  • Người dùng phải xác thực qua một dịch vụ serverless được quản lý.
  • Người dùng viết và đọc to-do, nhưng chủ yếu là đọc.
  • Database phải scale được và có throughput đọc cao.

Từng yêu cầu ở trên tương ứng với một quyết định kiến trúc cụ thể, và ta xây dần từng lớp.

Lớp đầu tiên giải quyết hai yêu cầu “REST API với HTTPS” và “serverless”:

Mobile client gọi REST HTTPS tới Amazon API Gateway → API Gateway invoke AWS Lambda → Lambda query Amazon DynamoDB. Song song đó, client authenticate với Amazon Cognito, và API Gateway dùng Cognito để verify authentication của mỗi request.

Đây là bộ tứ nền của mọi kiến trúc serverless: API Gateway (HTTPS + REST) → Lambda (logic) → DynamoDB (dữ liệu), với Cognito canh cửa.

Yêu cầu “người dùng tương tác trực tiếp với thư mục riêng của mình trong S3” không được giải bằng cách cho Lambda proxy file. Thay vào đó, Amazon Cognito cấp permissions cho Mobile client, và client store/retrieve files trực tiếp với Amazon S3.

Throughput đọc cao cho dữ liệu ít thay đổi

Phần tiêu đề “Throughput đọc cao cho dữ liệu ít thay đổi”

Yêu cầu “chủ yếu đọc, cần throughput đọc cao” được giải bằng cách thêm DAX làm caching layer phía trước DynamoDB. Luồng trở thành: Lambda query/read qua DAX → DynamoDB.

Bước cuối cùng là đặt thêm một tầng cache nữa, lần này ở mức API Gateway: bật CACHING OF RESPONSES để những request giống nhau không cần đi tiếp xuống Lambda.

Kiến trúc hoàn chỉnh của MyTodoList vì thế gồm: Mobile client → API Gateway (có cache response) → Lambda → DAX → DynamoDB; Cognito lo xác thực và cấp quyền để client nói chuyện thẳng với S3.

  • Serverless REST API: HTTPS, API Gateway, Lambda, DynamoDB.
  • Dùng Cognito để sinh credential tạm thời truy cập S3 bucket với policy bị giới hạn; nhờ đó người dùng ứng dụng truy cập trực tiếp tài nguyên AWS; pattern này áp dụng được cho DynamoDB, Lambda
  • Cache các lần đọc trên DynamoDB bằng DAX.
  • Cache các REST request ở mức API Gateway.
  • Bảo mật cho xác thực và phân quyền bằng Cognito.

Bài toán thứ hai là một website được host theo kiểu serverless, với các yêu cầu:

  • Website phải scale toàn cầu.
  • Blog rất ít khi được viết, nhưng được đọc thường xuyên.
  • Một phần website là file tĩnh thuần, phần còn lại là một REST API động.
  • Phải triển khai caching ở mọi nơi có thể.
  • Người dùng mới đăng ký phải nhận được email chào mừng.
  • Mỗi ảnh upload lên blog phải được sinh thumbnail.

Yêu cầu “scale toàn cầu” cho phần tĩnh: Client tương tác với các edge location của Amazon CloudFront (global distribution), và CloudFront lấy nội dung từ Amazon S3 làm origin.

Phục vụ nội dung tĩnh, toàn cầu và an toàn

Phần tiêu đề “Phục vụ nội dung tĩnh, toàn cầu và an toàn”

Có CDN rồi thì phải chặn đường đi tắt vào bucket. Thêm OAC: Origin Access Control giữa CloudFront và S3, cùng một bucket policy chỉ cho phép truy cập từ CloudFront Distribution. Khi đó người dùng không thể gọi thẳng S3 bỏ qua CloudFront.

Phần động được ghép vào bên cạnh phần tĩnh: Amazon API GatewayAWS Lambda (invoke) → DAX (caching layer) → DynamoDB (query/read), tất cả qua REST HTTPS.

Vì website phải scale toàn cầu, tầng dữ liệu cũng phải toàn cầu: thay DynamoDB thường bằng DynamoDB Global Tables, để dữ liệu được phục vụ ở nhiều region với độ trễ thấp.

Yêu cầu “người dùng mới nhận email chào mừng” được giải hoàn toàn bằng event, không cần polling:

DynamoDB bật DynamoDB Stream → stream các thay đổi → invoke một AWS Lambda → Lambda dùng IAM RoleSDK để gửi email qua Amazon Simple Email Service (SES).

Yêu cầu “mỗi ảnh upload phải có thumbnail”:

Client upload photos lên Amazon S3 (có thể qua Transfer acceleration, và phần tĩnh vẫn được phân phối qua CloudFront + OAC) → S3 trigger một AWS Lambda → Lambda ghi thumbnail vào Amazon S3. Ngoài Lambda, S3 cũng có thể bắn tới SQS hoặc SNS — phần này là tùy chọn (optional).

  • Nội dung tĩnh được phân phối bằng CloudFront + S3.
  • REST APIserverless, và không cần Cognito vì nó công khai (public).
  • Dùng DynamoDB Global Table để phục vụ dữ liệu toàn cầu — (cũng có thể dùng Aurora Global Database).
  • Bật DynamoDB Streams để trigger một Lambda function.
  • Lambda function đó có một IAM role cho phép dùng SES.
  • SES (Simple Email Service) được dùng để gửi email theo cách serverless.
  • S3 có thể trigger SQS / SNS / Lambda để thông báo về các event.

Bài toán thứ ba: chuyển sang kiến trúc micro service, với đặc điểm:

  • Nhiều service tương tác trực tiếp với nhau qua REST API.
  • Kiến trúc của từng micro service có thể khác nhau về hình thái.
  • Mục đích: có vòng đời phát triển gọn nhẹ hơn cho từng service.

Trong kiến trúc mẫu, Users gửi DNS Query tới Amazon Route 53 rồi gọi HTTPS vào từng service qua các tên miền riêng — service1.example.com, service2.example.com, service3.example.com. Mỗi service phía sau có hình thái hoàn toàn khác nhau:

Service Thành phần
service1 Amazon API GatewayAWS LambdaElastiCache
service2 Elastic Load BalancingAmazon EC2 trong Auto ScalingAmazon RDS
service3 Elastic Load BalancingECSDynamoDB

Đó chính là điều slide muốn nhấn: mỗi micro service được tự do chọn kiến trúc phù hợp nhất với nó.

Bạn tự do thiết kế từng micro service theo cách bạn muốn, và có hai nhóm pattern:

  • Synchronous patterns: API Gateway, Load Balancers.
  • Asynchronous patterns: SQS, Kinesis, SNS, Lambda triggers (S3).

Nhưng micro services cũng có các thách thức rất thật:

  • Overhead lặp lại mỗi khi tạo một microservice mới.
  • Vấn đề tối ưu mật độ / mức sử dụng server.
  • Độ phức tạp khi chạy đồng thời nhiều phiên bản của nhiều microservice.
  • Bùng nổ code phía client để tích hợp với rất nhiều service riêng lẻ.

Một phần các thách thức đó được giải bằng các pattern serverless:

  • API GatewayLambda tự scale và bạn trả tiền theo mức dùng.
  • Bạn có thể clone API dễ dàng, tái tạo lại môi trường.
  • Client SDK được sinh tự động thông qua tích hợp Swagger của API Gateway.

Bài toán thứ tư rất hay gặp trong đề thi vì nó dạy cách tối ưu mà không sửa kiến trúc.

Tình huống: bạn có một ứng dụng chạy trên EC2, thỉnh thoảng phát hành software update. Khi có bản cập nhật mới, hệ thống nhận rất nhiều request và nội dung được phân phối ồ ạt qua networkrất đắt. Bạn không muốn thay đổi ứng dụng, nhưng muốn tối ưu chi phí và CPU.

Ứng dụng nằm trong một Auto Scaling group trải trên Availability zone 1, 2 và 3, và các EC2 instance đọc file cập nhật từ một Amazon Elastic File System dùng chung.

Đặt Amazon CloudFront ở phía trước — giữ nguyên toàn bộ phần còn lại: Auto Scaling group trên 3 AZ và Amazon EFS không thay đổi gì.

  • Không phải thay đổi kiến trúc nào cả.
  • CloudFront sẽ cache các file software update ở edge.
  • File software update không động — chúng là tĩnh (không bao giờ thay đổi), nên cache rất hiệu quả.
  • Các EC2 instance của ta không serverless, nhưng CloudFront thì có, và CloudFront sẽ scale thay cho ta.
  • ASG sẽ không phải scale nhiều nữa, và ta tiết kiệm được rất nhiều chi phí EC2.
  • Ta cũng tiết kiệm được về tính sẵn sàng, chi phí băng thông network

Nói ngắn gọn: đây là cách dễ nhất để làm một ứng dụng đang tồn tại trở nên scale tốt hơn và rẻ hơn.

Bài toán Kiến trúc chốt lại
MyTodoList (mobile) API Gateway (REST HTTPS, cache response) → Lambda → DAX → DynamoDB; Cognito xác thực và cấp credential tạm thời để client truy cập thẳng S3
Pattern Cognito Cognito sinh credential tạm thời với policy bị giới hạn → app user truy cập trực tiếp S3, và pattern này dùng được cho DynamoDB, Lambda
Hai tầng cache DAX cache read của DynamoDB · API Gateway cache response của REST request
MyBlog.com — tĩnh CloudFront + S3, siết bằng OACbucket policy chỉ cho phép CloudFront Distribution
MyBlog.com — động API Gateway → Lambda → DAX → DynamoDB Global Tables (hoặc Aurora Global Database); API public nên không cần Cognito
Email chào mừng DynamoDB Streams → Lambda (có IAM Role) → SES gửi email, hoàn toàn serverless
Thumbnail Upload lên S3 (có thể dùng Transfer Acceleration) → trigger Lambda → ghi thumbnail vào S3; S3 cũng trigger được SQS / SNS / Lambda
Micro services Route 53 định tuyến từng subdomain tới từng service; mỗi service có kiến trúc riêng (API Gateway+Lambda+ElastiCache · ELB+EC2 ASG+RDS · ELB+ECS+DynamoDB)
Pattern micro services Sync: API Gateway, Load Balancer · Async: SQS, Kinesis, SNS, Lambda trigger (S3); serverless giúp auto scale, pay per usage, clone API, sinh SDK qua Swagger
Software update offloading Thêm CloudFront trước ASG + EFS: không sửa app, cache file tĩnh ở edge, ASG scale ít hơn, tiết kiệm EC2 và băng thông