Kiến trúc Serverless mẫu
1. Mobile application: MyTodoList
Phần tiêu đề “1. Mobile application: MyTodoList”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 REST API
Phần tiêu đề “Lớp REST API”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.
Cho người dùng truy cập S3
Phần tiêu đề “Cho người dùng truy cập S3”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.
Cache ngay tại API Gateway
Phần tiêu đề “Cache ngay tại API Gateway”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.
Những gì bài này dạy
Phần tiêu đề “Những gì bài này dạy”- 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.
2. Website serverless: MyBlog.com
Phần tiêu đề “2. Website serverless: MyBlog.com”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.
Phục vụ nội dung tĩnh, toàn cầu
Phần tiêu đề “Phục vụ nội dung tĩnh, toàn cầu”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.
Thêm REST API serverless công khai
Phần tiêu đề “Thêm REST API serverless công khai”Phần động được ghép vào bên cạnh phần tĩnh: Amazon API Gateway → AWS Lambda (invoke) → DAX (caching layer) → DynamoDB (query/read), tất cả qua REST HTTPS.
Dùng DynamoDB Global Tables
Phần tiêu đề “Dùng DynamoDB Global Tables”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.
Luồng email chào mừng người dùng
Phần tiêu đề “Luồng email chào mừng người dùng”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 Role và SDK để gửi email qua Amazon Simple Email Service (SES).
Luồng sinh thumbnail
Phần tiêu đề “Luồng sinh thumbnail”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).
Tổng kết kiến trúc website
Phần tiêu đề “Tổng kết kiến trúc website”- Nội dung tĩnh được phân phối bằng CloudFront + S3.
- REST API là serverless, 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.
3. Kiến trúc Micro Services
Phần tiêu đề “3. Kiến trúc Micro Services”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.
Môi trường micro services
Phần tiêu đề “Môi trường micro services”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 Gateway → AWS Lambda → ElastiCache |
| service2 | Elastic Load Balancing → Amazon EC2 trong Auto Scaling → Amazon RDS |
| service3 | Elastic Load Balancing → ECS → DynamoDB |
Đó 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ó.
Thảo luận về micro services
Phần tiêu đề “Thảo luận về micro services”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 Gateway và Lambda 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.
4. Offload việc phát hành software update
Phần tiêu đề “4. Offload việc phát hành software update”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 network — rất đắt. Bạn không muốn thay đổi ứng dụng, nhưng muốn tối ưu chi phí và CPU.
Hiện trạng
Phần tiêu đề “Hiện trạng”Ứ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.
Cách sửa rất đơn giản
Phần tiêu đề “Cách sửa rất đơn giản”Đặ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ì.
Vì sao lại là CloudFront?
Phần tiêu đề “Vì sao lại là CloudFront?”- 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.
Tóm tắt nhanh
Phần tiêu đề “Tóm tắt nhanh”| 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 OAC và bucket 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 |