AWS Serverless: Lambda
What’s serverless?
Serverless là một mô hình mới mà nhà phát triển không cần phải quản lý máy chủ.
Họ chỉ cần triển khai mã nguồn và các hàm (Functions) mà không phải lo về cơ sở hạ tầng bên dưới.
Ví dụ:
Khi bạn phát triển một ứng dụng web, thay vì phải cài đặt một máy chủ ảo EC2, cài đặt môi trường và deploy ứng dụng trên đó, bạn có thể chỉ cần upload đoạn mã lên dịch vụ AWS Lambda, và AWS sẽ tự động tạo máy chủ, chạy mã của bạn khi có yêu cầu, và tắt máy chủ đó khi không còn ai sử dụng. Bạn không cần lo lắng về các thao tác như bảo trì máy chủ hay tăng/giảm quy mô.
Ví dụ:
Giả sử bạn có một ứng dụng xử lý hình ảnh mà người dùng tải lên. Với cách tiếp cận serverless:
Bạn chỉ cần triển khai hàm Lambda để xử lý hình ảnh.
Khi người dùng tải ảnh lên, hàm Lambda sẽ tự động chạy, xử lý ảnh, và sau đó tắt đi khi hoàn thành công việc.
Ví dụ trong AWS Lambda:
AWS Lambda là một dịch vụ FaaS (Function as a Service), nơi bạn có thể viết một hàm, ví dụ như một hàm để xử lý thông tin đơn hàng từ người dùng. Hàm này có thể tự động kích hoạt khi người dùng gửi đơn hàng qua API hoặc khi có sự kiện từ hệ thống.
def handle_order(order_details):
# Code xử lý đơn hàng
print("Processing order", order_details)
4. Ban đầu Serverless đồng nghĩa với FaaS
Ban đầu, Serverless chỉ đơn thuần liên quan đến FaaS - tức là các hàm nhỏ thực thi mà không cần phải lo về máy chủ. AWS Lambda là một ví dụ điển hình của điều này.
Ví dụ về FaaS trong thực tế:
Một developer có thể triển khai một hàm Lambda để tính toán và trả về kết quả. Hàm này chỉ được gọi và thực thi khi có một sự kiện kích hoạt (ví dụ như có người gửi yêu cầu từ ứng dụng di động hoặc website). Khi sự kiện kết thúc, Lambda cũng tự động kết thúc, và bạn chỉ phải trả tiền cho thời gian Lambda hoạt động.
5. Serverless bao gồm nhiều dịch vụ khác
Ngoài việc chỉ bao gồm FaaS, khái niệm Serverless đã được mở rộng ra để bao gồm các dịch vụ quản lý khác như cơ sở dữ liệu, hệ thống tin nhắn, lưu trữ. AWS cung cấp nhiều dịch vụ "Serverless" bao gồm:
Amazon S3: Lưu trữ đối tượng tĩnh như hình ảnh, video, tệp dữ liệu.
Amazon DynamoDB: Cơ sở dữ liệu NoSQL serverless cho phép mở rộng linh hoạt.
Amazon SQS (Simple Queue Service): Hàng đợi tin nhắn serverless.
Amazon SNS (Simple Notification Service): Dịch vụ gửi thông báo serverless.
Ví dụ về kết hợp các dịch vụ serverless:
Bạn có một ứng dụng e-commerce và bạn muốn xử lý đơn hàng:
Khi người dùng đặt hàng, dữ liệu được lưu vào DynamoDB.
Hệ thống sau đó phát ra một sự kiện trong SNS để thông báo tới hệ thống xử lý thanh toán.
Một hàm AWS Lambda sẽ được kích hoạt để xử lý thanh toán.
Sau khi thanh toán thành công, thông tin sản phẩm được lưu vào S3 để lưu trữ và báo cáo.
Tất cả các dịch vụ này hoạt động theo mô hình serverless - bạn không phải lo lắng về việc quản lý máy chủ.
Lưu ý:
Serverless không có nghĩa là không có máy chủ.
Máy chủ vẫn tồn tại, nhưng bạn không phải quản lý, cấu hình, hoặc nhìn thấy chúng.
1. Các dịch vụ Serverless phổ biến trong AWS:
AWS Lambda: Chạy code mà không cần quản lý máy chủ.
DynamoDB: Cơ sở dữ liệu NoSQL Serverless.
AWS Cognito: Xác thực và quản lý người dùng.
AWS API Gateway: Xây dựng API RESTful.
Amazon S3: Lưu trữ đối tượng.
SNS (Simple Notification Service) & SQS (Simple Queue Service): Dịch vụ nhắn tin.
AWS Kinesis Data Firehose: Xử lý và truyền dữ liệu theo thời gian thực.
Aurora Serverless: Cơ sở dữ liệu tự động điều chỉnh quy mô.
Step Functions: Điều phối quy trình làm việc.
Fargate: Quản lý container không cần quản lý máy chủ.
2. Kiến trúc minh họa Serverless trên AWS:
Người dùng (Users):
Truy cập nội dung tĩnh thông qua S3 Bucket.
Truy cập API qua API Gateway.
Đăng nhập qua Cognito.
Quy trình API:
API Gateway nhận yêu cầu từ người dùng.
Chuyển tiếp yêu cầu đến Lambda.
Lambda xử lý và truy vấn dữ liệu từ DynamoDB.
Luồng hoạt động:
Người dùng truy cập nội dung tĩnh từ S3.
Thông qua API Gateway, người dùng gọi API.
Lambda xử lý logic.
Dữ liệu được lưu trữ hoặc truy xuất từ DynamoDB.
AWS EC2 và AWS Lambd
1. Amazon EC2
Virtual Servers in the Cloud: Amazon EC2 cung cấp các máy chủ ảo để thuê và có thể cài đặt OS, phần mềm và cấu hình như một máy chủ vật lý.
Limited by RAM and CPU: Dung lượng CPU, Ram, ổ cứng giới hạn dựa trên cấu hình máy chủ bạn chọn.
Continuously running: Sau khi khởi động một EC2 instance, nó sẽ chạy liên tục cho đến khi được tắt thủ công.
Scaling means intervention to add/remove servers: Để mở rộng quy mô (scaling), bạn cần phải can thiệp thủ công để thêm hoặc xóa bớt máy chủ.
Ví dụ về Amazon EC2:
Trường hợp sử dụng: Một trang web thương mại điện tử chạy trên một máy chủ EC2.
Mở rộng: Khi lượng truy cập tăng cao vào Black Friday, bạn phải thêm nhiều máy EC2 mới thủ công hoặc sử dụng Auto Scaling Group để tự động mở rộng.
Chi phí: Bạn trả tiền cho mỗi giờ máy chủ chạy, ngay cả khi nó không xử lý yêu cầu nào.
2. AWS Lambda
AWS Lambda là một dịch vụ compute theo mô hình serverless
Các đặc điểm chính của AWS Lambda:
Virtual functions – no servers to manage!: AWS Lambda cho phép bạn chạy các đoạn mã nhỏ dưới dạng "hàm" mà không cần quản lý máy chủ.
Limited by time – short executions: Mỗi hàm Lambda chỉ được chạy trong một khoảng thời gian ngắn (tối đa 15 phút). Lambda thích hợp cho các tác vụ nhỏ gọn và ngắn hạn, không phù hợp với các công việc chạy dài như EC2.
Run on-demand: Hàm Lambda chỉ chạy khi có yêu cầu/trigger cụ thể (ví dụ: khi có người truy cập API).
Scaling is automated!: AWS Lambda tự động mở rộng quy mô để xử lý nhiều yêu cầu cùng lúc.
Ví dụ về AWS Lambda:
Trường hợp sử dụng: Xử lý hình ảnh tải lên từ người dùng.
- Khi một người dùng tải ảnh lên S3, Lambda tự động kích hoạt để tạo ra hình thu nhỏ (thumbnail) cho bức ảnh.
Mở rộng: Không cần can thiệp thủ công; nếu 1,000 người tải ảnh cùng lúc, Lambda tự động mở rộng để xử lý.
Chi phí: Bạn chỉ trả tiền cho thời gian mà hàm Lambda thực thi.
Lợi ích của AWS Lambda
1. Easy Pricing
Pay per request and compute time: chỉ phải trả tiền cho số lượng request và thời gian mà Lambda thực thi.
Miễn phí trong hạn mức nhất định (Free Tier):
1,000,000 yêu cầu mỗi tháng.
400,000 GB-giờ thời gian tính toán mỗi tháng.
Ví dụ:
Nếu bạn có một hàm Lambda xử lý ảnh tải lên từ người dùng, bạn chỉ trả tiền cho thời gian thực thi mỗi lần ảnh được xử lý.
Nếu bạn xử lý ít hơn 1 triệu yêu cầu mỗi tháng, bạn sẽ không phải trả phí.
2. Integrated with the whole AWS suite of services
Lambda dễ dàng tích hợp với các dịch vụ khác như Amazon S3, DynamoDB, API Gateway, SNS, SQS.
Ví dụ:
Khi một tệp được tải lên S3, Lambda có thể được kích hoạt tự động để xử lý tệp đó.
Khi một mục mới được thêm vào DynamoDB, Lambda có thể kích hoạt để xử lý dữ liệu.
3. Integrated with many programming languages
Lambda hỗ trợ nhiều ngôn ngữ lập trình phổ biến:
- Node.js (JavaScript), Python, Java, C# (.NET Core) / PowerShell, Ruby, Custom Runtime API
AWS Lambda cũng cho phép sử dụng Custom Runtime cho các ngôn ngữ mà Lambda không hỗ trợ chính thức. Điều này có nghĩa là bạn có thể chạy bất kỳ ngôn ngữ nào, miễn là bạn xây dựng runtime theo chuẩn của Lambda Runtime API*. Các ngôn ngữ phổ biến trong cộng đồng như* Rust hay Golang thường được sử dụng qua Custom Runtime.
Lambda Container Image
Hàm Lambda có thể chạy trong Docker Container.
Container phải tuân theo Lambda Runtime API.
ECS / Fargate phù hợp hơn nếu bạn muốn chạy các container lớn hơn với Docker.
Ví dụ:
Bạn muốn đóng gói toàn bộ môi trường Python kèm thư viện riêng vào Docker Image và chạy trên Lambda.
Fargate phù hợp hơn nếu bạn cần quản lý nhiều container phức tạp.
Tiêu chí | AWS Lambda | Amazon EC2 | AWS Fargate |
Quản lý máy chủ | Không cần quản lý máy chủ | Cần tự quản lý máy chủ | Không cần quản lý |
Tính linh hoạt | Hỗ trợ nhiều ngôn ngữ | Hỗ trợ mọi môi trường | Hỗ trợ Docker Container |
Tự động mở rộng | Có, tự động | Có, nhưng cần Auto Scaling | Có, tự động |
Chi phí | Trả theo thời gian chạy | Trả theo giờ | Trả theo CPU, RAM |
4. Easy monitoring through AWS CloudWatch
AWS Lambda tích hợp với Amazon CloudWatch, giúp dễ dàng giám sát hiệu suất, lỗi và thời gian thực thi các hàm Lambda.
5. Easy to get more resources per function
Có thể cấu hình hàm Lambda với RAM lên đến 10GB.
Tăng RAM cũng đồng thời tăng và cải thiện CPU và hiệu suất mạng.
Ví dụ: Nếu một hàm Lambda xử lý các tác vụ tính toán phức tạp như mã hóa video, bạn có thể tăng RAM để giảm thời gian xử lý.
3. So sánh giữa EC2 và Lambda:
Tiêu chí | Amazon EC2 | AWS Lambda |
Quản lý máy chủ | Có, cần quản lý máy chủ | Không, AWS quản lý toàn bộ |
Thời gian chạy | Liên tục | Ngắn hạn (tối đa 15 phút) |
Mở rộng (Scaling) | Thủ công hoặc Auto Scaling | Tự động hoàn toàn |
Chi phí | Trả theo giờ | Trả theo thời gian thực thi |
Sử dụng lý tưởng | Ứng dụng dài hạn, phức tạp | Các tác vụ nhỏ, sự kiện theo yêu cầu |
AWS Lambda Intergration
1. Tích hợp AWS Lambda với các dịch vụ chính:
1.1 API Gateway
- Ví dụ: API Gateway sẽ nhận yêu cầu từ API, truyền request tới hàm Lambda, và Lambda sẽ xử lý logic đăng ký sau đó trả về kết quả cho khách hàng.
1.2 Kinesis
- Ví dụ: Một công ty có thể sử dụng Kinesis để thu thập dữ liệu cảm biến từ hàng ngàn thiết bị IoT và Lambda sẽ xử lý dữ liệu đó theo thời gian thực, chẳng hạn như phát hiện sự kiện hoặc thực hiện các hành động theo ngưỡng.
1.3 DynamoDB
- Ví dụ: Mỗi khi có một bản ghi mới được thêm vào DynamoDB, Lambda có thể tự động được kích hoạt để thực hiện một số hành động như ghi log, gửi email thông báo, hoặc tính toán số liệu thống kê.
1.4 S3 (Amazon Simple Storage Service)
- Ví dụ: Mỗi khi người dùng tải lên một hình ảnh mới trong S3, Lambda có thể tự động xử lý hình ảnh, tạo ảnh thumbnail (hình thu nhỏ), sau đó lưu ảnh thu nhỏ lại vào S3.
1.5 CloudFront
- Ví dụ: Lambda@Edge có thể được sử dụng để thay đổi nội dung được phân phối từ CloudFront, chẳng hạn như tùy chỉnh header HTTP trước khi trả về cho người dùng.
1.6 CloudWatch Events (EventBridge)
- Ví dụ: Bạn có thể cấu hình một CRON job (tác vụ lặp lại theo lịch trình) để Lambda tự động chạy một công việc mỗi giờ, như kiểm tra tình trạng tài nguyên.
1.7 CloudWatch Logs
- Ví dụ: Khi Lambda gặp lỗi trong quá trình thực thi, các thông tin chi tiết về lỗi sẽ được ghi lại trong CloudWatch Logs để bạn có thể phân tích và khắc phục sự cố.
1.8 SNS (Simple Notification Service)
- Ví dụ: Sau khi Lambda hoàn thành xử lý, nó có thể gửi thông báo tới một dịch vụ khác hoặc tới người dùng thông qua SNS, chẳng hạn như gửi email thông báo.
1.9 SQS (Simple Queue Service)
- Ví dụ: Khi một yêu cầu xử lý được gửi tới hàng đợi SQS, Lambda có thể tự động đọc tin nhắn và xử lý nó.
1.10 Cognito
- Ví dụ: Lambda có thể được sử dụng để xử lý logic tùy chỉnh, chẳng hạn như gửi email xác nhận khi một người dùng mới đăng ký qua Cognito.
2. Ví dụ về Serverless Integration
2.1 Ví dụ: Tạo thumbnail từ hình ảnh (Serverless Thumbnail Creation)
Trigger: Khi người dùng tải một hình ảnh mới lên S3, sự kiện này sẽ kích hoạt hàm Lambda.
Lambda xử lý: Lambda sẽ tạo ra một phiên bản ảnh thumbnail nhỏ hơn từ ảnh gốc.
Lưu trữ kết quả:
Thumbnail được lưu lại trong một thư mục khác trên S3.
Metadata (thông tin về ảnh như kích thước, tên, ngày tạo) được ghi vào DynamoDB.
2.2 Ví dụ: CRON Job không dùng server (Serverless CRON Job)
Trigger: Một sự kiện định kỳ được cấu hình qua CloudWatch Events hoặc EventBridge để kích hoạt Lambda mỗi giờ.
Lambda thực thi: Lambda sẽ chạy một nhiệm vụ tự động, ví dụ như lấy dữ liệu từ một API và ghi kết quả vào DynamoDB.
AWS Lambda Pricing
AWS Lambda sử dụng mô hình định giá “Pay-as-you-go” - chúng ta chỉ trả tiền cho:
1. Số lượng yêu cầu (Pay per call)
1,000,000 yêu cầu đầu tiên miễn phí mỗi tháng.
Sau đó, chi phí là $0.20 cho mỗi 1 triệu yêu cầu.
- Tương đương: $0.0000002 mỗi yêu cầu
2. Thời gian thực thi (Pay per duration)
Thời gian thực thi được tính từ khi Lambda bắt đầu chạy đến khi hoàn tất
AWS tính phí dựa trên GB-giây (GB-seconds).
400,000 GB-giây mỗi tháng miễn phí.
Mỗi GB-giây tương ứng với tài nguyên RAM bạn cấu hình.
Sau khi hết 400,000 GB-giây, chi phí là $1.00 cho mỗi 600,000 GB-giây
Cách tính GB-giây:
1 GB RAM x 400,000 giây = 400,000 GB-giây miễn phí
128 MB RAM x 3,200,000 giây = 400,000 GB-giây miễn phí
Ví dụ minh họa:
Hàm Lambda sử dụng 1 GB RAM và chạy trong 500,000 giây:
400,000 giây đầu tiên miễn phí.
100,000 giây còn lại = ~166,666 GB-giây.
Chi phí: $0.28 (100,000 GB-giây nằm trong mức $1.00 cho 600,000 GB-giây).
3. Vì sao AWS Lambda rất phổ biến?
Chi phí thấp - Miễn phí cho nhiều tác vụ nhỏ:
- Với hạn mức miễn phí rộng rãi, nhiều doanh nghiệp không phải trả bất kỳ chi phí nào.
Trả tiền dựa trên nhu cầu thực tế:
- Không lãng phí tài nguyên máy chủ khi không sử dụng.
Phù hợp với khối lượng công việc không liên tục:
- Ví dụ: Tác vụ xử lý hình ảnh, xử lý dữ liệu IoT, API Gateway.
Tự động mở rộng:
- Lambda tự động mở rộng (auto-scale) mà không cần cấu hình phức tạp.
Không cần quản lý máy chủ:
- Bạn chỉ cần tập trung viết mã và xử lý logic, tất cả các công việc về cơ sở hạ tầng, bảo trì máy chủ, và mở rộng tài nguyên đều do AWS quản lý.
Ví dụ:
Xử lý ảnh:
Bạn có thể sử dụng Lambda để tạo ảnh thumbnail mỗi khi người dùng tải ảnh lên S3. Lambda chỉ chạy khi có hình ảnh mới, và bạn chỉ trả tiền cho thời gian Lambda xử lý việc tạo thumbnail.
API Backend:
Nếu bạn xây dựng một ứng dụng web hoặc di động, Lambda có thể xử lý các yêu cầu backend. Mỗi khi người dùng gửi yêu cầu, Lambda sẽ được kích hoạt để thực hiện các tác vụ như lưu trữ dữ liệu, xác thực, và trả về kết quả.
So Sánh Pricing của AWS Lambda và AWS EC2
Tiêu chí | AWS Lambda | Amazon EC2 |
Chi phí cơ bản | Trả theo yêu cầu và thời gian | Trả theo giờ (luôn tính dù không hoạt động) |
Mức miễn phí | 1 triệu yêu cầu + 400,000 GB-giây | Không có miễn phí tương tự |
Thích hợp cho | Tác vụ ngắn, không liên tục | Ứng dụng dài hạn, chạy 24/7 |
Mở rộng | Tự động | Cần cấu hình Auto Scaling |
Synchronous Invocations
1. Định nghĩa Synchronous Invocations
Synchronous Invocation là cách gọi hàm AWS Lambda theo kiểu đồng bộ, trong đó:
Kết quả được trả về ngay lập tức sau khi hàm Lambda thực thi xong.
Xử lý lỗi phải được thực hiện ở phía client (ví dụ: API Gateway, SDK, CLI).
Bao gồm cơ chế retry (thử lại) và exponential backoff (tăng dần thời gian giữa các lần thử lại)
Ví dụ cơ chế hoạt động
SDK/CLI (Lệnh gọi trực tiếp qua AWS CLI hoặc SDK):
Client gọi trực tiếp hàm Lambda.
Lambda xử lý và trả về phản hồi.
API Gateway (Proxy qua API Gateway):
Client gọi API Gateway (ví dụ: một API RESTful nhận request từ user qua API Gateway).
API Gateway chuyển tiếp yêu cầu đến Lambda (ví dụ: xác thực người dùng).
Lambda xử lý và trả kết quả ngược lại qua API Gateway.
2. Các dịch vụ sử dụng Synchronous Invocation
2.1 User Invoked (Gọi trực tiếp bởi người dùng)
Elastic Load Balancing (Application Load Balancer):
Khi ALB nhận được yêu cầu từ người dùng, nó sẽ đồng bộ kích hoạt Lambda và chờ kết quả trước khi trả về cho người dùng.
- Ví dụ: Một người dùng truy cập trang web, ALB sẽ chuyển tiếp yêu cầu tới Lambda để xử lý dữ liệu và trả về trang web đã được render.
Amazon API Gateway:
Khi một API Gateway endpoint được gọi, nó sẽ đồng bộ gọi Lambda để xử lý dữ liệu và trả về phản hồi cho người dùng.
- Ví dụ: Bạn xây dựng một API để lấy thông tin sản phẩm. API Gateway nhận yêu cầu từ người dùng, chuyển tiếp tới Lambda, Lambda truy vấn cơ sở dữ liệu và trả về kết quả thông qua API Gateway.
Amazon CloudFront (Lambda@Edge):
Lambda@Edge cho phép bạn chạy hàm Lambda ở các edge location của CloudFront.
- Ví dụ: Khi người dùng yêu cầu một trang web từ CloudFront, Lambda@Edge có thể được kích hoạt để thêm các tiêu đề (header) bảo mật vào phản hồi.
Amazon S3 Batch:
S3 Batch Operations cho phép bạn thực hiện các tác vụ trên hàng triệu đối tượng S3.
- Ví dụ: Khi bạn cần thay đổi quyền truy cập cho tất cả các tệp trong S3, bạn có thể sử dụng S3 Batch để đồng bộ gọi Lambda và thực hiện thay đổi trên từng tệp.
2.2 Service Invoked (Dịch vụ kích hoạt Lambda)
Amazon Cognito:
Ví dụ: Khi người dùng đăng ký/đăng nhặp qua Cognito, Cognito có thể đồng bộ gọi Lambda để kiểm tra thông tin đăng ký và gửi email xác nhận.
AWS Step Functions:
Step Functions có thể đồng bộ gọi Lambda trong quá trình thực hiện workflow, chờ đợi Lambda hoàn thành để tiếp tục các bước tiếp theo.
- Ví dụ: Khi Step Functions chạy một workflow xử lý đơn hàng, nó có thể gọi Lambda để kiểm tra tình trạng kho hàng trước khi tiếp tục bước xác nhận đơn hàng.
2.3 Other Services (Các dịch vụ khác)
**Amazon Lex (**Xử lý yêu cầu chatbot):
Ví dụ: Khi người dùng hỏi chatbot Lex về tình trạng đơn hàng, Lex sẽ gọi Lambda để truy xuất thông tin từ cơ sở dữ liệu và trả lời cho người dùng.
Amazon Alexa (Xử lý yêu cầu từ thiết bị Alexa):
Ví dụ: Khi người dùng yêu cầu Alexa bật đèn, Lambda sẽ được gọi để gửi lệnh tới hệ thống điều khiển đèn và trả về phản hồi ngay lập tức.
Amazon Kinesis Data Firehose (Chuyển tiếp và xử lý dữ liệu streaming):
Ví dụ: Khi dữ liệu thời gian thực được truyền qua Kinesis Firehose, Lambda có thể được đồng bộ gọi để lọc và định dạng dữ liệu trước khi lưu vào S3 hoặc Redshift.
3. So sánh Synchronous và Asynchronous Invocations
Tiêu chí | Synchronous Invocation | Asynchronous Invocation |
Phản hồi | Ngay lập tức | Sau khi xử lý hoàn tất |
Xử lý lỗi | Phía client | AWS quản lý retry |
Dịch vụ phổ biến | API Gateway, ALB | S3, SNS, EventBridge |
Khi nào dùng? | Ứng dụng yêu cầu phản hồi ngày | Xử lý tác vụ nền, không cần phản hồi ngay |
Lambda Integration with ALB
1. Khái niệm cơ bản
ALB (Application Load Balancer) có thể gọi AWS Lambda thông qua HTTP/HTTPS.
ALB giúp bạn phân phối các yêu cầu HTTP/HTTPS từ client tới backend, và trong trường hợp này, backend của bạn sẽ là hàm Lambda..
Lambda Function phải được đăng ký trong một Target Group:
Tạo một Target Group cho Lambda.
Đăng ký hàm Lambda vào Target Group này.
Tạo hoặc cấu hình ALB để phân phối yêu cầu tới Target Group chứa Lambda.
ALB hoạt động như một Proxy:
Nhận yêu cầu HTTP/HTTPS từ Client.
Chuyển tiếp (invoke) yêu cầu đến Lambda Function.
Trả lại phản hồi từ Lambda về Client.
Quy trình hoạt động:
Client (người dùng) gửi yêu cầu HTTP/HTTPS đến ALB.
ALB xử lý yêu cầu và chuyển tiếp (Invoke Sync) đến Lambda.
Lambda thực thi logic và gửi phản hồi lại ALB.
ALB gửi phản hồi HTTP/HTTPS cho Client.
Khi nào nên sử dụng?
Ứng dụng có lưu lượng biến động: Nếu bạn có một ứng dụng mà lưu lượng người dùng không đều, Lambda rất phù hợp vì bạn không phải trả tiền cho thời gian chờ đợi không tải (idle time) như với EC2.
Xử lý logic đơn giản: Lambda rất phù hợp cho các ứng dụng xử lý đơn giản như các trang web tĩnh, xử lý yêu cầu API đơn giản, hoặc các tác vụ ngắn hạn.
Ví dụ thực tế về sử dụng ALB với Lambda
Xử lý yêu cầu API đơn giản
Giả sử bạn có một hàm Lambda để xử lý yêu cầu từ một API. Bạn muốn mọi yêu cầu tới API sẽ được chuyển tới Lambda thông qua ALB.
Tạo Lambda Function: Đây là một hàm Lambda đơn giản để trả về thông tin người dùng.
def lambda_handler(event, context): return { 'statusCode': 200, 'body': 'Hello from Lambda via ALB!' }
Tạo một Application Load Balancer để xử lý các yêu cầu HTTP.
Đăng ký Lambda vào Target Group
Cấu hình Listener cho ALB để ALB lắng nghe các yêu cầu HTTP/HTTPS trên các cổng và chuyển tiếp yêu cầu tới target group chứa Lambda.
Test:
Khi người dùng truy cập vào endpoint của ALB, yêu cầu sẽ được chuyển tới Lambda. Lambda xử lý yêu cầu và trả về kết quả "Hello from Lambda via ALB!".
5. So sánh ALB và API Gateway với Lambda
Cả ALB và API Gateway đều có thể được sử dụng để tích hợp với Lambda, tuy nhiên, chúng có một số khác biệt:
ALB | API Gateway |
Phù hợp cho các ứng dụng cần xử lý lưu lượng lớn và hiệu suất cao. | Phù hợp cho các API RESTful, với nhiều tính năng quản lý API như xác thực, giới hạn tốc độ (throttling). |
Dễ sử dụng với các ứng dụng có yêu cầu đơn giản về HTTP(S). | Có nhiều tính năng quản lý API như xử lý CORS, cache, và xác thực. |
Thường dùng cho các ứng dụng web và microservices. | Thích hợp cho các API phức tạp, có yêu cầu về bảo mật. |
Không có các tính năng chi tiết về quản lý API. | Có thể tích hợp với các API phức tạp, quản lý nhiều loại yêu cầu. |
Hướng dẫn về ALB to Lambda: HTTP to JSON
Cấu trúc Request Payload trong Lambda
Khi ALB nhận được một yêu cầu HTTP từ người dùng, nó sẽ chuyển tiếp yêu cầu này tới Lambda dưới dạng một JSON payload. JSON này chứa tất cả các thông tin liên quan đến yêu cầu HTTP, bao gồm phương thức HTTP, query string parameters, header, và body của yêu cầu.
Các thành phần chính:
requestContext.elb
: Thông tin về ELB (Elastic Load Balancer), bao gồm target group ARN. Điều này cho biết ALB nào đã kích hoạt Lambda.httpMethod
: Đây là phương thức HTTP (GET, POST, PUT, DELETE, v.v.) được sử dụng trong yêu cầu.path
: Đường dẫn của API hoặc endpoint mà người dùng đã gọi. Ví dụ, nếu người dùng gọi/lambda
, phần này sẽ cho biết đó là endpoint/lambda
.queryStringParameters
: Các tham số chuỗi truy vấn (query string) được truyền kèm trong URL dưới dạng cặp khóa-giá trị (key/value pairs).headers
: Tất cả các header HTTP mà client gửi kèm, cũng được truyền dưới dạng cặp khóa-giá trị (key/value pairs).body
: Phần thân của yêu cầu (nếu có). Thường là các yêu cầu POST hoặc PUT sẽ có phần thân chứa dữ liệu.isBase64Encoded
: Thông tin này chỉ ra xem liệu phần thân (body) có được mã hóa dưới dạng Base64 hay không. Nếu true, bạn cần giải mã trước khi xử lý.
Ví dụ: Xử lý GET request với query string
def lambda_handler(event, context):
# Lấy phương thức HTTP
method = event['httpMethod']
# Lấy đường dẫn yêu cầu
path = event['path']
# Lấy tham số query string
query = event.get('queryStringParameters', {}).get('query', 'No query provided')
# Lấy header User-Agent
user_agent = event['headers'].get('User-Agent', 'Unknown')
# Lấy phần body (nếu có)
body = event.get('body', 'No body provided')
# Xây dựng phản hồi
response = {
'statusCode': 200,
'body': f"Method: {method}, Path: {path}, Query: {query}, User-Agent: {user_agent}, Body: {body}"
}
return respons
Hướng dẫn về Lambda to ALB: JSON to HTTP
Cấu trúc Response từ Lambda
Khi Lambda hoàn tất việc xử lý một yêu cầu HTTP, nó trả về một JSON response với các thông tin như status code, headers, và body. Sau đó, ALB sẽ chuyển đổi response này thành một HTTP response gửi lại cho client.
Các thành phần chính trong JSON response của Lambda:
statusCode
: Mã trạng thái HTTP (HTTP Status Code) trả về cho client, ví dụ: 200 OK, 404 Not Found, 500 Internal Server Error, v.v.statusDescription
: Mô tả của mã trạng thái HTTP, ví dụ:"200 OK"
.headers
: Các HTTP headers chứa thông tin bổ sung về response, ví dụ như loại nội dung (Content-Type
), thông tin về bảo mật (Authorization
), v.v. Headers được truyền dưới dạng cặp key/value.body
: Nội dung chính của phản hồi. Đây có thể là dữ liệu văn bản (như HTML, JSON) hoặc dữ liệu nhị phân (binary data).isBase64Encoded
: Thông tin này cho biết liệu phần body có được mã hóa dưới dạng Base64 hay không. Nếu true, bạn cần giải mã trước khi sử dụng dữ liệu.
Ví dụ minh họa về phản hồi từ Lambda
Giả sử bạn có một hàm Lambda được kích hoạt qua ALB để trả về một trang HTML chào mừng người dùng. Bạn có thể cấu hình hàm Lambda để trả về JSON như sau:
def lambda_handler(event, context):
return {
"statusCode": 200,
"statusDescription": "200 OK",
"headers": {
"Content-Type": "text/html; charset=utf-8"
},
"body": "<h1>Hello world!</h1>",
"isBase64Encoded": False
}
ALB Multi Header Values
1. Multi-Header Values là gì?
ALB có khả năng hỗ trợ nhiều giá trị cho cùng một header hoặc query string parameter.
- Điều này thường gặp khi bạn cần gửi nhiều thông tin cùng lúc trong một tham số hoặc header, ví dụ: nhiều tham số tìm kiếm hoặc nhiều giá trị bảo mật.
Khi multi-value headers được kích hoạt, các giá trị này sẽ được hiển thị dưới dạng mảng (arrays) trong đối tượng sự kiện và phản hồi của AWS Lambda.
Để sử dụng tính năng Multi-Header Values, cần kích hoạt tính năng này trên ALB khi cấu hình target group.
Cách cấu hình trên ALB:
Trong giao diện quản lý của ALB, bạn tìm đến phần cấu hình của Target Group.
Tại đây, bạn kích hoạt tính năng Multi-Value Headers cho target group liên quan đến Lambda.
2. Cách ALB xử lý Multi-Header Values
- Client gửi một yêu cầu HTTP chứa nhiều giá trị cho cùng một tham số (ví dụ:
name
).
http://example.com/path?name=foo&name=bar
ALB nhận yêu cầu và chuyển tiếp dữ liệu đến Lambda dưới dạng JSON.
Query string parameter
name
có nhiều giá trị được hiển thị dưới dạng một mảng (array) trong JSON{ "queryStringParameters": { "name": ["foo", "bar"] }, "headers": { "X-Custom-Header": ["value1", "value2"] } }
Lambda đọc dữ liệu từ
queryStringParameters
và xử lý các giá trị trong mảng.
Ví dụ về một hàm Lambda để xử lý một yêu cầu với nhiều giá trị cho tham số name
và một custom header X-Custom-Header
:
def lambda_handler(event, context):
# Lấy các giá trị của query string "name"
names = event['queryStringParameters'].get('name', [])
# Lấy các giá trị của header "X-Custom-Header"
custom_header_values = event['headers'].get('X-Custom-Header', [])
# Xử lý logic tùy theo yêu cầu
response_body = {
"names_received": names,
"custom_header_values_received": custom_header_values
}
# Trả về kết quả
return {
"statusCode": 200,
"body": json.dumps(response_body),
"headers": {
"Content-Type": "application/json"
}
ALB + Lambda - Permissions
1. Lambda Resource Policy là gì?
Lambda Resource Policy là chính sách kiểm soát truy cập cấp phép cho các dịch vụ hoặc tài khoản AWS khác gọi hàm Lambda.
Trong trường hợp này, Application Load Balancer (ALB) cần có quyền gọi hàm Lambda.
2. Cấu trúc của Lambda Resource Policy
Trong ví dụ này, chính sách tài nguyên của Lambda bao gồm một statement (tuyên bố), trong đó xác định ai có quyền gì trên tài nguyên nào.
{
"Statement": {
"Effect": "Allow",
"Principal": {
"Service": "elasticloadbalancing.amazonaws.com"
},
"Action": "Lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-west-2:123456789012:function:alb-function"
}
}
Giải thích từng phần:
Effect
:Allow
: Chỉ định rằng hành động mà chúng ta sẽ xác định trong mục Action sẽ được cho phép (cho phép ALB thực hiện hành động mà chúng ta xác định sau).
Principal
:Xác định dịch vụ được phép thực hiện action (
elasticloadbalancing.amazonaws.com
~ ALB).⇒ ALB sẽ được phép gọi Lambda.
Action
:lambda:InvokeFunction
: Xác định hành động ALB được phép thực hiện.⇒
InvokeFunction
cho phép ALB gọi hàm Lambda.
Resource
:ARN (Amazon Resource Name) của hàm Lambda mà ALB sẽ gọi.
Cấu trúc ARN:
arn:aws:lambda:<region>:<account-id>:function:<function-name>
3. Cách cấu hình chính sách này cho Lambda của bạn
Cấu hình Resource Policy trong AWS Lambda?
Truy cập AWS Lambda Console:
- Vào "Configuration" → "Permissions".
Chỉnh sửa Resource Policy:
- Dán JSON Policy từ ví dụ trên.
Kiểm tra ARN và Dịch vụ:
- Đảm bảo ARN Lambda chính xác và
Principal
làelasticloadbalancing.amazonaws.com
.
- Đảm bảo ARN Lambda chính xác và
Lưu Policy:
- Lưu cấu hình và kiểm tra ALB có thể gọi Lambda không.
Bước 1: Xác định ARN của Lambda
Đầu tiên, bạn cần tìm ARN của hàm Lambda mà bạn muốn cho phép ALB gọi. Bạn có thể tìm ARN này trong trang quản lý Lambda trên AWS Console.
Ví dụ: arn:aws:lambda:us-west-2:123456789012:function:alb-function
Bước 2: Cấu hình chính sách quyền
Bạn có thể sử dụng AWS CLI hoặc giao diện web của AWS Console để thêm chính sách quyền cho Lambda của mình. Nếu sử dụng AWS CLI, bạn có thể chạy lệnh sau để thêm quyền:
aws lambda add-permission \\
--function-name alb-function \\
--statement-id allow-alb-invoke \\
--principal elasticloadbalancing.amazonaws.com \\
--action lambda:InvokeFunction \\
--source-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/my-target-group/50dc6c495c0c9188
function-name
: Tên của hàm Lambda mà bạn muốn cho phép ALB gọi.statement-id
: Một định danh duy nhất cho chính sách quyền này (ví dụ,allow-alb-invoke
).principal
: Dịch vụ cần quyền (trong trường hợp này là ALB).action
: Hành động mà ALB được phép thực hiện, cụ thể làlambda:InvokeFunction
.source-arn
: ARN của Target Group liên kết với ALB.
Bước 3: Kiểm tra quyền
Sau khi thêm chính sách, bạn có thể kiểm tra lại quyền của Lambda để đảm bảo rằng ALB có thể kích hoạt Lambda đúng cách. Bạn có thể thực hiện việc này trên AWS Console hoặc thông qua lệnh CLI:
aws lambda get-policy --function-name alb-function
4. Ví dụ thực tế về tích hợp ALB và Lambda
Giả sử bạn có một hàm Lambda để xử lý các yêu cầu HTTP từ người dùng thông qua Application Load Balancer (ALB). Bạn cần cho phép ALB gọi hàm Lambda của mình khi người dùng gửi yêu cầu tới ALB.
Ví dụ: Xử lý yêu cầu HTTP từ ALB với Lambda
Tạo hàm Lambda:
Hàm Lambda này sẽ xử lý yêu cầu từ ALB và trả về phản hồi.
Ví dụ về một hàm Lambda đơn giản bằng Python:
def lambda_handler(event, context): return { "statusCode": 200, "body": "Request processed by Lambda" }
Cấu hình ALB và Target Group:
- Tạo một Application Load Balancer (ALB) và liên kết nó với một Target Group mà hàm Lambda là một "mục tiêu" (target).
Thêm chính sách quyền cho Lambda:
- Sử dụng lệnh
aws lambda add-permission
để cho phép ALB gọi hàm Lambda, như trong ví dụ CLI ở trên.
- Sử dụng lệnh
Test:
- Khi người dùng gửi yêu cầu HTTP tới ALB, ALB sẽ chuyển tiếp yêu cầu đó tới Lambda, và Lambda sẽ xử lý rồi trả về phản hồi.
So sánh Lambda Resource Policy và IAM Policy
Tiêu chí | Lambda Resource Policy | IAM Policy |
Phạm vi | Áp dụng cho hàm Lambda cụ thể | Áp dụng cho người dùng IAM hoặc dịch vụ AWS |
Mục đích | Cho phép dịch vụ AWS truy cập Lambda | Quản lý quyền truy cập chung |
Ví dụ | Cho phép ALB gọi Lambda | Cho phép User gọi Lambda qua CLI |
Quản lý | Quản lý trực tiếp trong Lambda | Quản lý qua IAM Console |
AWS Lambda – Asynchronous Invocations
1. Asynchronous Invocations là gì?
Asynchronous Invocation là cách gọi hàm Lambda theo kiểu bất đồng bộ, trong đó:
Yêu cầu được đặt vào một Event Queue (hàng đợi sự kiện).
Lambda xử lý yêu cầu ngay khi có thể, không cần chờ kết quả ngay lập tức.
Nếu lỗi xảy ra, Lambda sẽ tự động thử lại
3 lần thử lại
đợi 1 phút sau lần thứ nhất, sau đó là 2 phút
2. Quy trình kích hoạt Lambda không đồng bộ
Kích hoạt Sự Kiện (Trigger Event):
S3 (khi file mới được tải lên).
SNS (khi một thông báo mới được gửi).
CloudWatch Events (khi một sự kiện lịch trình xảy ra).
Event Queue (Hàng đợi sự kiện):
- Yêu cầu từ dịch vụ (S3, SNS) được đặt vào hàng đợi sự kiện.
Xử Lý Lambda (Function Processing):
Lambda đọc từ Event Queue và thực thi hàm.
Điều này diễn ra không đồng bộ, tức là dịch vụ ban đầu (S3, SNS, v.v.) không cần phải chờ đợi kết quả từ Lambda.
Nếu lỗi xảy ra, Lambda tự động retry (thử lại).
Retry Logic (Logic thử lại):
Tổng cộng 3 lần thử lại.
1 phút chờ sau lần đầu tiên.
2 phút chờ sau lần thứ hai.
DLQ (Dead-Letter Queue)
- Nếu Lambda thất bại sau 3 lần thử, sự kiện có thể được chuyển vào SNS hoặc SQS để xử lý sau.
3. Đảm bảo tính idempotent cho hàm Lambda
Một khái niệm quan trọng khi làm việc với asynchronous invocations là phải đảm bảo rằng hàm Lambda của bạn là idempotent.
Idempotent có nghĩa là khi bạn chạy lại một hàm với cùng một sự kiện, kết quả sẽ giống nhau.
Điều này đảm bảo rằng việc retry (thử lại) không làm phát sinh dữ liệu trùng lặp hoặc lỗi.
Ví dụ về idempotent:
- Nếu Lambda xử lý đơn đặt hàng, hãy đảm bảo rằng nếu đơn hàng đã được xử lý, nó sẽ không được xử lý lại khi Lambda thử lại yêu cầu.
4. CloudWatch Logs và DLQ
Duplicate Logs in CloudWatch
Khi Lambda retry, sẽ có nhiều bản ghi log trùng lặp trong CloudWatch Logs.
Điều này giúp bạn theo dõi mỗi lần retry.
Dead-Letter Queue (DLQ)
DLQ là nơi lưu trữ các sự kiện thất bại sau nhiều lần thử lại, Có thể sử dụng:
SNS (Simple Notification Service): Thông báo khi một sự kiện thất bại.
SQS (Simple Queue Service): Lưu trữ các sự kiện thất bại để xử lý sau.
Ví dụ về DLQ với SQS:
Bạn có thể cấu hình một hàng đợi SQS để nhận tất cả các sự kiện không thể xử lý sau khi Lambda đã thử lại 3 lần mà vẫn gặp lỗi. Sau đó, bạn có thể tạo một quy trình để xử lý hoặc ghi log các sự kiện này nhằm khắc phục vấn đề.
5. Lợi ích của Asynchronous Invocations
Tốc độ xử lý cao: Lambda có thể xử lý hàng nghìn yêu cầu đồng thời và Không cần chờ từng yêu cầu hoàn tất trước khi xử lý yêu cầu tiếp theo.
Ví dụ: Bạn có 1.000 tệp cần xử lý. Thay vì chờ đợi mỗi lần tải tệp lên được xử lý, bạn có thể gửi tất cả tệp tới Lambda thông qua S3, và Lambda sẽ tự động xử lý từng tệp trong nền mà không ảnh hưởng đến các thao tác khác.
Tự động Retry: Lambda tự động thử lại mà không cần can thiệp thủ công.
Xử lý sự kiện nền (Background Processing): Thích hợp cho các tác vụ không cần phản hồi ngay lập tức, như xử lý file lớn từ S3, gửi email qua SNS.
6. Ví dụ minh họa về Asynchronous Invocations
Xử lý tệp mới tải lên trong S3
Giả sử bạn có một ứng dụng tải ảnh lên S3 và bạn muốn mỗi khi một ảnh mới được tải lên, Lambda sẽ tự động tạo ra một ảnh thu nhỏ (thumbnail).
Sự kiện: Người dùng tải file lên S3.
Asynchronous Invocation: Sự kiện được đặt vào Event Queue.
Lambda: Lambda được kích hoạt và xử lý file, xử lý dữ liệu (ví dụ: tạo thumbnail ảnh).
Kết quả: Nếu Lambda thất bại 3 lần, sự kiện sẽ được gửi vào DLQ để xử lý sự kiện thất bại sau này.
Trong ví dụ này, Lambda được cấu hình để gửi các sự kiện thất bại tới SQS tên là my-dlq:
aws lambda update-function-configuration \\
--function-name myLambdaFunction \\
--dead-letter-config TargetArn=arn:aws:sqs:us-west-2:123456789012:my-dlq
Các dịch vụ AWS kích hoạt Lambda không đồng bộ
S3 | Tệp tải lên/xóa | Xử lý dữ liệu file |
SNS | Tin nhắn SNS | Gửi thông báo, xử lý tin nhắn |
CloudWatch Events | Sự kiện định kỳ | Tự động hóa tác vụ |
CodeCommit | Thay đổi mã nguồn | CI/CD Pipeline |
CodePipeline | Trong pipeline | Xác thực và triển khai mã |
SES | Email gửi/nhận | Xử lý nội dung email |
Config | Thay đổi cấu hình | Đảm bảo tuân thủ chính sách |
IoT | Dữ liệu IoT | Phân tích dữ liệu từ cảm biến |
Amazon Simple Storage Service (S3)
Trigger sự kiện: Khi một file mới được tải lên, cập nhật hoặc xóa khỏi S3 bucket.
Xử lý tệp tải lên S3: chuyển đổi định dạng tệp, tạo thumbnail, lưu trữ metadata vào db...
Ví dụ: Tải một ảnh lên S3 → Lambda tự động tạo thumbnail và lưu lại vào một bucket S3 khác.
Amazon Simple Notification Service (SNS)
Trigger sự kiện: Khi một tin nhắn SNS được gửi đi.
Sử dụng Lambda: Xử lý thông báo, thực hiện hành động cụ thể dựa trên tin nhắn.
Ví dụ: Khi có giao dịch thành công trên website, SNS sẽ gửi thông báo đến Lambda → Lambda xử lý thông báo này, ví dụ như ghi log hoặc gửi email xác nhận.
Amazon CloudWatch Events / EventBridge
Trigger sự kiện: Dựa trên lịch trình hoặc quy tắc sự kiện (Rules).
Sử dụng Lambda: Tự động hóa tác vụ, thực thi script, xử lý dữ liệu định kỳ.’
Ví dụ: Lambda chạy mỗi ngày lúc 12:00 PM để sao lưu dữ liệu vào S3.
AWS CodeCommit
Trigger sự kiện: Khi có thay đổi mã nguồn (new branch, new tag, new push).
Sử dụng Lambda: Tự động hóa các quy trình CI/CD.
Ví dụ: Khi một đoạn code mới được push, Lambda có thể được kích hoạt để tự động kiểm tra mã (ví dụ: kiểm tra style code, hoặc chạy các unit test).
AWS CodePipeline
Trigger sự kiện: Trong các giai đoạn khác nhau của pipeline (Build, Deploy).
Sử dụng Lambda: Thực hiện kiểm tra, thông báo, hoặc chuyển đổi dữ liệu.
Ví dụ: Lambda kiểm tra mã nguồn sau bước Build.
Amazon CloudWatch Logs
Trigger sự kiện: Khi một log mới được ghi vào CloudWatch Logs.
Sử dụng Lambda: Phân tích log, cảnh báo hoặc xử lý log cụ thể.
Ví dụ: Lambda phát hiện lỗi trong log và gửi thông báo qua SNS.
Amazon Simple Email Service (SES)
Trigger sự kiện: Khi có email được gửi hoặc nhận qua SES.
Sử dụng Lambda: Xử lý nội dung email, lọc email spam.
Ví dụ: Lambda xử lý email xác nhận và gửi mã OTP cho người dùng
AWS CloudFormation
Trigger sự kiện: Trong quá trình triển khai stack CloudFormation.
Sử dụng Lambda: Tạo tài nguyên động hoặc thực hiện cấu hình tùy chỉnh.
Ví dụ: Tự động tạo IAM Role khi stack được triển khai.
AWS Config
Trigger sự kiện: Khi cấu hình tài nguyên AWS thay đổi.
Sử dụng Lambda: Kiểm tra tuân thủ (compliance), áp dụng biện pháp khắc phục.
Ví dụ:
- Lambda tự động ngắt tài nguyên không tuân thủ chính sách bảo mật.
AWS IoT và AWS IoT Events
Trigger sự kiện: Khi thiết bị IoT gửi dữ liệu hoặc khi có một sự kiện IoT xảy ra.
Sử dụng Lambda: Phân tích dữ liệu, gửi cảnh báo, tự động thực hiện hành động.
**Ví dụ:**Lambda phân tích dữ liệu nhiệt độ từ thiết bị IoT và gửi cảnh báo nếu vượt quá giới hạn.
CloudWatch Events và EventBridge
1. CloudWatch Events và EventBridge là gì?
EventBridge (trước đây là CloudWatch Events) là một dịch vụ giúp bạn kích hoạt AWS Lambda và các dịch vụ AWS khác dựa trên các sự kiện hoặc lịch trình cụ thể:
CRON hoặc Lịch Trình: Tự động hóa tác vụ dựa trên thời gian định sẵn.
State Changes (Thay đổi trạng thái): Phản ứng với sự kiện từ dịch vụ AWS khác (ví dụ: thay đổi trạng thái trong CodePipeline).
EventBridge hoạt động như một hệ thống bus sự kiện kết nối các dịch vụ AWS với nhau.
2. Luồng Hoạt Động của EventBridge
Tiêu chí | CRON/Rate Rule | State Change Rule |
Cách kích hoạt | Lịch trình thời gian cụ thể | Dựa trên sự kiện trạng thái |
Ví dụ phổ biến | Sao lưu hàng ngày, dọn dẹp file | Thông báo khi pipeline thành công |
Tính linh hoạt | Định kỳ cố định | Linh hoạt dựa trên trạng thái |
Dịch vụ phổ biến | EC2, S3, DynamoDB | CodePipeline, CloudFormation |
CRON hoặc Rate EventBridge Rule (Lịch Trình Định Kỳ)
CRON/Rate EventBridge Rule là một loại quy tắc (rule) cho phép kích hoạt các hành động định kỳ theo một lịch biểu cụ thể (tương tự như CRON jobs trong Unix/Linux).
- Trigger thời gian cụ thể: Được cấu hình bằng CRON hoặc Rate Expression.
📊 Ví dụ:
Kịch bản: Lambda tự động sao lưu dữ liệu từ cơ sở dữ liệu vào S3 mỗi ngày vào lúc 12:00 PM.
Lệnh CRON:
cron(0 12 * * ? *)
→ Chạy vào 12:00 PM hàng ngày. (rate(1 hour)
→ Chạy mỗi giờ một lần){ "schedule": "cron(0 12 * * ? *)", "target": { "arn": "arn:aws:lambda:us-east-1:123456789012:function:daily-backup" } }
{ "scheduleExpression": "rate(1 hour)" }
State Changes EventBridge Rule (Thay đổi trạng thái)
Trigger khi có sự kiện thay đổi trạng thái.
Ví dụ:
Kịch bản: Khi pipeline trong AWS CodePipeline chuyển từ trạng thái
InProgress
sangSucceeded
, Lambda được gọi để thông báo qua SNS.{ "source": ["aws.codepipeline"], "detail-type": ["CodePipeline Pipeline Execution State Change"], "detail": { "state": ["SUCCEEDED"] }, "target": { "arn": "arn:aws:lambda:us-east-1:123456789:function:notify-pipeline-success" } }
Cấu hình AWS Lambda với EventBridge
Tạo Rule trong EventBridge:
- Chọn Schedule Rule (CRON/Rate) hoặc Event Pattern (State Changes).
Chọn Target:
- Chọn Lambda Function là mục tiêu (target).
Thiết lập Quyền (IAM Policy):
Đảm bảo EventBridge có quyền gọi hàm Lambda.
Policy Mẫu:
{ "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:us-east-1:123456789:function:my-lambda-function" }
Kiểm tra Logs:
- Xác minh qua CloudWatch Logs để đảm bảo Lambda chạy đúng.
S3 Events Notifications
1. S3 Evenet Notifications là gì
Amazon S3 có thể kích hoạt các thông báo sự kiện khi có hành động cụ thể xảy ra trên bucket.
Các loại sự kiện S3 hỗ trợ:
S3:ObjectCreated: Khi một đối tượng mới được tạo trong S3 (ví dụ: tải lên tệp mới).
S3:ObjectRemoved: Khi một đối tượng bị xóa khỏi S3.
S3:ObjectRestore: Khi một tệp được khôi phục từ Glacier
S3:Replication: Khi dữ liệu được sao chép giữa các bucket.
2. Filtering theo tên đối tượng (Object name filtering)
AWS S3 cho phép áp dụng bộ lọc để chỉ kích hoạt thông báo cho tệp cụ thể.
Ví dụ: Chỉ tạo thumbnail cho các tệp ảnh
.jpg
."Filter": { "Key": { "FilterRules": [ {"Name": "suffix", "Value": ".jpg"} ] } }
3. Case studies
Tạo Thumbnail cho Ảnh Tải Lên
Sự kiện:
S3:ObjectCreated
Quy trình:
Người dùng tải ảnh (.jpg) lên bucket S3.
S3 kích hoạt Lambda thông qua Event Notification.
Lambda tạo thumbnail và lưu trở lại vào bucket
{
"Id": "image-upload-trigger",
"Events": ["s3:ObjectCreated:*"],
"Filter": {
"Key": {
"FilterRules": [
{"Name": "suffix", "Value": ".jpg"}
]
}
},
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:create-thumbnail"
}
Gửi Thông Báo qua SNS
Sự kiện:
S3:ObjectCreated
Quy trình:
Tệp mới được tải lên S3.
S3 gửi thông báo qua SNS Topic.
SNS có thể gửi email hoặc tin nhắn SMS đến người quản trị.
Xử Lý Dữ Liệu Bằng SQS và Lambda
Sự kiện:
S3:ObjectCreated
Quy trình:
Tệp mới được tạo trên S3.
S3 gửi sự kiện đến SQS Queue.
Lambda đọc từ hàng đợi SQS và xử lý tệp.
4. Lưu ý
4.1 Thời Gian Gửi Thông Báo (Delivery Latency)
S3 thường gửi thông báo sự kiện chỉ trong vài giây.
Trong một số trường hợp, có thể mất một phút hoặc lâu hơn, có thể do:
Độ trễ trong hệ thống S3 backend.
Khối lượng lớn các sự kiện đồng thời.
📊 Ví dụ:
Người dùng tải một file lớn lên bucket S3.
Lambda được kích hoạt nhưng trễ 1 phút do hệ thống S3 đang xử lý nhiều sự kiện cùng lúc.
⇒ Không nên sử dụng S3 Event Notification cho các tác vụ yêu cầu độ trễ thấp.
4.2 Xử Lý Nhiều Ghi (Multiple Writes on a Single Object)
Khi có nhiều ghi (writes) vào cùng một đối tượng không có phiên bản (non-versioned object) trong cùng một thời điểm:
Có thể chỉ có một thông báo sự kiện được gửi.
Các lần ghi tiếp theo có thể bị bỏ qua trong thông báo.
Ví dụ:
Hai người dùng đồng thời ghi dữ liệu vào tệp
report.csv
trong bucket S3.S3 có thể chỉ gửi một thông báo sự kiện thay vì hai.
Lambda có thể không phát hiện được lần ghi thứ hai.
⇒ Nếu bạn cần đảm bảo mọi lần ghi đều được thông báo, bạn nên bật Versioning (Phiên bản hóa) trên bucket.
4.3 Giải Pháp: Bật Versioning (Phiên Bản Hóa)
Versioning giúp đảm bảo rằng mỗi lần ghi vào một đối tượng sẽ tạo ra một phiên bản mới.
Lợi ích:
Mỗi lần ghi sẽ kích hoạt một thông báo sự kiện riêng biệt.
Giảm nguy cơ mất thông báo sự kiện.
Ví dụ:
Không có Versioning:
Người dùng A ghi vào tệp
report.csv
.Người dùng B ghi đè lên tệp
report.csv
.Chỉ có một thông báo sự kiện được gửi.
Có Versioning:
Người dùng A ghi vào tệp
report.csv
→ Phiên bản 1 (v1
) được tạo → Sự kiện 1 được gửi.Người dùng B ghi vào tệp
report.csv
→ Phiên bản 2 (v2
) được tạo → Sự kiện 2 được gửi.
Cách bật Versioning trên S3:
Vào bucket S3 trên AWS Console.
Chọn "Properties" → "Bucket Versioning".
Chọn "Enable".
Lệnh AWS CLI:
aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Enabled
Simple S3 Event Pattern - Metadata Sync
Đây là một mô hình phổ biến trong AWS khi tích hợp Amazon S3 với AWS Lambda, Amazon RDS, và Amazon DynamoDB để đồng bộ hóa metadata. Đây là một ví dụ quan trọng về cách event-driven architecture (kiến trúc dựa trên sự kiện) hoạt động trong môi trường AWS
1. Mô hình sự kiện của S3 và đồng bộ hóa metadata
S3 Bucket:
- Khi một tệp mới được tải lên bucket S3, một sự kiện (event) được kích hoạt.
AWS Lambda:
Lambda được kích hoạt khi có sự kiện từ S3.
Lambda đọc metadata (siêu dữ liệu) của tệp mới và xử lý logic cần thiết.
Cơ sở dữ liệu RDS và DynamoDB:
Lambda đồng bộ hóa siêu dữ liệu vào:
RDS Table: Dữ liệu quan hệ (Relational Data).
DynamoDB Table: Dữ liệu phi quan hệ (NoSQL Data).
Tại Sao Cần Đồng Bộ Metadata?
Đảm bảo dữ liệu tải lên S3 được phản ánh chính xác trong các cơ sở dữ liệu backend.
Cải thiện khả năng tìm kiếm và quản lý thông tin liên quan đến file.
Tăng cường tính toàn vẹn của dữ liệu trong các hệ thống khác nhau.
2. Chi tiết mô hình
- Trigger Sự Kiện từ S3
Sự kiện:
S3:ObjectCreated:*
Khi một tệp mới được tải lên bucket S3, sự kiện này được kích hoạt.
Ví dụ cấu hình sự kiện S3:
{
"Id": "sync-metadata",
"Events": ["s3:ObjectCreated:*"],
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:update-metadata"
}
Xử Lý Logic trong Lambda
Truy xuất Metadata từ S3: Tên tệp, kích thước, thời gian tải lên, loại MIME, v.v.
Ghi vào RDS Table: Thêm một bản ghi mới chứa metadata tệp vào RDS.
Ghi vào DynamoDB Table: Cập nhật bảng DynamoDB với metadata tệp.
Ví dụ mã Lambda (Python + Boto3):
import boto3 def lambda_handler(event, context): s3 = boto3.client('s3') rds_client = boto3.client('rds') dynamodb = boto3.resource('dynamodb') bucket_name = event['Records'][0]['s3']['bucket']['name'] file_key = event['Records'][0]['s3']['object']['key'] # Lấy Metadata từ S3 metadata = s3.head_object(Bucket=bucket_name, Key=file_key) file_size = metadata['ContentLength'] content_type = metadata['ContentType'] # Cập nhật RDS # (giả định có kết nối và bảng RDS được cấu hình) rds_client.execute_statement( database='metadata_db', sql=f"INSERT INTO files (name, size, type) VALUES ('{file_key}', {file_size}, '{content_type}')" ) # Cập nhật DynamoDB table = dynamodb.Table('MetadataTable') table.put_item( Item={ 'FileName': file_key, 'Size': file_size, 'Type': content_type } ) return {"status": "success"}
- Cập Nhật RDS và DynamoDB
3. Ứng dụng
Quản lý Tệp Đa Phương Tiện (Media Files)
Sự kiện:
S3:ObjectCreated
Lambda Logic: Đồng bộ siêu dữ liệu của tệp video và ảnh lên RDS và DynamoDB.
Ứng dụng:
RDS: Truy vấn báo cáo, thống kê.
DynamoDB: Truy cập nhanh khi người dùng yêu cầu thông tin file qua API.
Quản lý Log Files
Sự kiện:
S3:ObjectCreated
Lambda Logic: Truy xuất metadata file log và lưu trữ vào RDS/DynamoDB.
Ứng dụng:
RDS: Truy vấn báo cáo lỗi.
DynamoDB: Tìm kiếm nhanh log cụ thể.
Lambda - Event Source Mapping
1. Event Source Mapping là gì?
Event Source Mapping là một tính năng trong AWS Lambda giúp tự động đọc dữ liệu (polling) từ các nguồn sự kiện như: Kinesis Data Streams, SQS và SQS FIFO Queue, DynamoDB Streams
Lambda thực hiện polling (lấy dữ liệu) từ các nguồn sự kiện này, sau đó xử lý theo từng lô dữ liệu (event batch).
2. Cách hoạt động của Event Source Mapping
Luồng Xử Lý Dữ Liệu (Hình minh họa):
Nguồn Sự Kiện (Event Source)
Nguồn sự kiện có thể là Kinesis, SQS, hoặc DynamoDB Streams.
Dữ liệu được ghi vào nguồn sự kiện này.
Event Source Mapping (ESM)
Lambda sử dụng Event Source Mapping (ESM) để poll dữ liệu (lấy dữ liệu).
Dữ liệu được lấy theo từng lô (batch of records).
Gửi Dữ Liệu Đến Lambda
Lambda được kích hoạt với một lô dữ liệu (batch).
Lambda xử lý dữ liệu này đồng bộ (synchronously) và trả về kết quả.
Trả Về Kết Quả Cho Nguồn Sự Kiện
- Sau khi xử lý xong, Lambda có thể xác nhận (acknowledge) rằng lô dữ liệu đã được xử lý thành công.
3. Tính Chất Chung (Common Denominator)
Dữ liệu được poll (lấy) từ nguồn sự kiện:
Lambda không tự động nhận sự kiện từ Kinesis, SQS, hay DynamoDB Streams.
Lambda poll (hỏi nguồn sự kiện) theo chu kỳ để lấy dữ liệu.
Hàm Lambda được gọi đồng bộ (synchronously):
Lambda xử lý từng lô dữ liệu một cách đồng bộ.
Nếu Lambda thất bại, dữ liệu có thể được retry hoặc đẩy vào Dead-Letter Queue (DLQ).
4. Các Nguồn Sự Kiện Phổ Biến
Kinesis Data Streams
Mô tả: Nền tảng dữ liệu thời gian thực, xử lý dữ liệu streaming.
Kịch bản sử dụng: Phân tích log thời gian thực, xử lý dữ liệu IoT.
Ví dụ:
Kinesis nhận dữ liệu từ cảm biến IoT.
Lambda đọc dữ liệu từ Kinesis, xử lý thông tin, và lưu kết quả vào DynamoDB.
SQS (Simple Queue Service)
Mô tả: Hàng đợi tin nhắn (Message Queue) được dùng để tách rời các thành phần hệ thống.
Kịch bản sử dụng: Xử lý hàng đợi các yêu cầu API, phân phối công việc.
Ví dụ:
Một ứng dụng đặt hàng gửi tin nhắn vào SQS Queue.
Lambda đọc tin nhắn, xác thực thông tin, và cập nhật vào cơ sở dữ liệu.
DynamoDB Streams
Mô tả: Ghi lại các thay đổi trong bảng DynamoDB.
Kịch bản sử dụng: Phân tích thay đổi dữ liệu, đồng bộ dữ liệu.
Cách hoạt động:
Bản ghi thay đổi trong DynamoDB được ghi vào DynamoDB Stream.
Lambda poll dữ liệu từ Stream.
Lambda xử lý dữ liệu và ghi kết quả vào dịch vụ khác.
Ví dụ:
Khi một bản ghi mới được thêm vào DynamoDB, sự kiện được ghi vào Stream.
Lambda xử lý dữ liệu và gửi thông báo qua SNS.
5. Retry và Error Handling (Xử Lý Lỗi)
Nếu Lambda thất bại trong việc xử lý một lô dữ liệu:
Kinesis và DynamoDB Streams: Lambda sẽ retry lô dữ liệu cho đến khi hết hạn thời gian lưu trữ của dữ liệu.
SQS: Dữ liệu có thể được retry hoặc gửi vào Dead-Letter Queue (DLQ).
5. Điểm khác biệt của Event Source Mapping so với Asynchronous Invocations
Synchronous Invocations: Với Event Source Mapping, Lambda được kích hoạt một cách đồng bộ, tức là Lambda chỉ được kích hoạt khi có sự kiện mới từ nguồn và thực thi khi dữ liệu đã được lấy từ nguồn.
Asynchronous Invocations: Ngược lại, trong các kích hoạt không đồng bộ, Lambda có thể tự động nhận sự kiện từ các nguồn như S3 hoặc SNS mà không cần polling.
AWS Lambda tích hợp với Kinesis Data Streams và DynamoDB Streams
Việc sử dụng streams (luồng dữ liệu) kết hợp với Lambda rất quan trọng trong các hệ thống xử lý dữ liệu theo thời gian thực hoặc khi cần giám sát sự thay đổi trong cơ sở dữ liệu DynamoDB. Điều này cũng là một chủ đề quan trọng trong kỳ thi AWS Certified Developer - Associate. Chúng ta sẽ cùng giải thích từng phần trong nội dung trên ảnh và lấy ví dụ minh họa để bạn dễ hiểu hơn.
Tổng Quan về Streams & AWS Lambda
AWS Lambda có thể xử lý dữ liệu từ các dịch vụ streaming như Amazon Kinesis và DynamoDB Streams.
Dữ liệu được xử lý theo lô (batches) và theo thứ tự (in-order processing) cho mỗi partition key hoặc shard.
Event Source Mapping đảm bảo rằng dữ liệu được đọc, phân lô và gửi đến Lambda một cách tối ưu.
1. Event Source Mapping và Iterator trong mỗi Shard
Lambda tạo một iterator (bộ lặp) cho mỗi shard (trong Kinesis) hoặc partition key (trong DynamoDB Streams).
Các iterator này đảm bảo rằng dữ liệu được đọc tuần tự (in-order) cho mỗi shard hoặc partition key.
Shard là một đơn vị lưu trữ dữ liệu trong stream
Các tùy chọn bắt đầu xử lý:
Dữ liệu mới (From New Items): Chỉ xử lý các mục mới được thêm sau khi Lambda được kích hoạt.
Từ đầu (From Beginning): Bắt đầu từ bản ghi đầu tiên trong shard hoặc stream.
Từ thời gian cụ thể (From Timestamp): Bắt đầu từ một mốc thời gian cụ thể.
Ví dụ Kinesis: Một Stream Kinesis nhận dữ liệu liên tục từ các thiết bị IoT. Lambda được cấu hình để bắt đầu xử lý từ thời gian hiện tại (Now).
2. Dữ liệu không bị xóa khỏi stream
Dữ liệu không bị xóa khỏi Kinesis hoặc DynamoDB Streams sau khi Lambda xử lý.
Điều này giúp các dịch vụ hoặc consumer khác cũng có thể đọc dữ liệu từ cùng một shard hoặc partition key.
Ví dụ minh họa:
- Ví dụ: Khi một bảng DynamoDB được cập nhật, các thay đổi sẽ được ghi lại trong DynamoDB Stream. Lambda có thể xử lý các sự kiện này, nhưng các ứng dụng khác cũng có thể đọc cùng một stream để đồng bộ hóa dữ liệu với các hệ thống khác.
3. Xử lý lưu lượng thấp bằng batch window
Batch Window: Cho phép Lambda chờ một khoảng thời gian để thu thập đủ bản ghi trước khi xử lý.
Hữu ích trong các trường hợp lưu lượng dữ liệu thấp trong stream.
Batch Window là khoảng thời gian Lambda đợi để thu thập các bản ghi từ stream trước khi xử lý chúng cùng một lúc
Ví dụ minh họa:
- Ví dụ về Batch Window trong Kinesis: Một hệ thống giám sát giao dịch chỉ có vài giao dịch mỗi phút. Thay vì kích hoạt Lambda cho mỗi giao dịch, bạn có thể cấu hình batch window để đợi 5 giây và xử lý tất cả các giao dịch trong khoảng thời gian đó cùng một lúc. Điều này giúp giảm số lần gọi Lambda và tối ưu chi phí.
4. Xử lý nhiều batch song song từ mỗi shard
Lambda có thể xử lý tối đa 10 batches đồng thời/sốngng cho mỗi shard hoặc partition key.
Tuy nhiên, thứ tự xử lý (in-order processing) vẫn được đảm bảo cho từng partition key.
Ví dụ minh họa:
Xử lý nhiều batch trong Kinesis: Một ứng dụng phân tích giao thông ghi lại dữ liệu từ hàng triệu phương tiện. Dữ liệu được đẩy vào Kinesis Stream và phân phối vào nhiều shard khác nhau dựa trên partition key (ví dụ: biển số xe). Lambda có thể xử lý dữ liệu từ nhiều shard song song, nhưng dữ liệu của từng phương tiện (cùng partition key) sẽ được xử lý theo thứ tự thời gian.
Một shard trong Kinesis chứa 1,000 bản ghi. Lambda có thể chia các bản ghi thành 10 lô và xử lý chúng đồng thời.
5. Quy trình xử lý dữ liệu bằng Lambda và Streams
Dưới đây là quy trình xử lý dữ liệu khi kết hợp Lambda và Streams như Kinesis và DynamoDB Streams:
Stream Poller (Công cụ kiểm tra stream) kiểm tra từng shard trong Kinesis hoặc DynamoDB Stream để tìm các bản ghi mới.
Record Processor (Bộ xử lý bản ghi) lấy các bản ghi này và phân loại chúng vào các batch (gói) dựa trên shard.
Mỗi batch được xử lý bởi một batcher riêng biệt, và sau đó được chuyển đến Lambda để xử lý.
Lambda Invoker (Bộ kích hoạt Lambda) sẽ kích hoạt hàm Lambda để xử lý các batch này.
Ví dụ chi tiết:
- Ví dụ về DynamoDB Streams và Lambda: Khi một bảng DynamoDB cập nhật dữ liệu (thêm mới, cập nhật, hoặc xóa mục), sự kiện này sẽ được ghi lại vào DynamoDB Stream. Stream Poller kiểm tra từng shard trong stream để tìm các thay đổi mới. Sau đó, các thay đổi này được phân chia thành các batch và Lambda sẽ xử lý từng batch một, đảm bảo các thay đổi trên cùng một partition key (ví dụ: cùng khách hàng) được xử lý theo thứ tự.
- Đảm Bảo Thứ Tự (In-order Processing)
Thứ tự xử lý vẫn được duy trì trong cùng một shard hoặc partition key.
Nếu một lô dữ liệu gặp lỗi, Lambda sẽ retry cho đến khi thành công.
Ví dụ: Partition key Device-123
có 10 bản ghi. Lambda đảm bảo rằng bản ghi 1
được xử lý trước bản ghi 2
.
Chi Tiết Quy Trình Xử Lý (Hình Minh Họa)
Shard và Partition Key:
- Shard
A
chứa các bản ghi được chia thành các lô (1, 2, 3).
- Shard
Record Processor (Bộ xử lý bản ghi):
- Dữ liệu từ shard được đọc bởi Record Processor và chia thành các batch (Batches 1, 2, 3).
Batcher:
- Mỗi batch được gửi đến một Batcher để chuẩn bị xử lý.
Lambda Invoker:
Mỗi batch được gửi đến một phiên bản Lambda riêng biệt để xử lý song song.
Mỗi batch được xử lý đồng bộ.
Stream & Lambda - Error Handling
1. Retry Logic (Logic Thử Lại)
Mặc định: Nếu Lambda gặp lỗi trong quá trình xử lý batch, toàn bộ batch (toàn bộ chứ không chỉ những sự kiên lỗi) sẽ được retry (thử lại) cho đến khi:
Lambda xử lý thành công.
Dữ liệu trong batch hết hạn (Expiration Time).
Điều này đảm bảo:
Thứ tự xử lý (In-order processing) vẫn được bảo toàn cho shard hoặc partition key.
Không có batch nào bị bỏ qua.
Ví dụ Kinesis: Giả sử bạn có một Kinesis Stream ghi lại các giao dịch mua hàng. Một batch gồm 10 giao dịch được gửi đến Lambda để xử lý. Nếu Lambda gặp lỗi ở giao dịch thứ 5, toàn bộ 10 giao dịch sẽ được xử lý lại, chứ không chỉ riêng giao dịch thứ 5 và tiếp tục retry batch này cho đến khi thành công hoặc đến khi dữ liệu trong batch hết hạn (7 ngày với Kinesis).
2. Đảm bảo xử lý theo thứ tự (In-order Processing) và Tạm Dừng Shard (Shard Pause)
Khi xảy ra lỗi: Việc xử lý trên shard (Kinesis) hoặc partition key (DynamoDB) sẽ tạm dừng (pause) cho đến khi lỗi được giải quyết.
Ý nghĩa: Tránh tình trạng Lambda tiếp tục xử lý các batch khác trong khi batch bị lỗi vẫn chưa được giải quyết và đảm bảo các sự kiện từ cùng một shard luôn được xử lý đúng theo thứ tự thời gian
Ví dụ:
Shard
shard-001
gặp lỗi trong batchbatch-45
.Lambda tạm dừng xử lý shard
shard-001
cho đến khi batchbatch-45
được xử lý thành công.
3. Tùy chỉnh Event Source Mapping
Chúng ta có thể điều chỉnh Event Source Mapping để xử lý lỗi hiệu quả hơn, bao gồm các tùy chọn:
3.1 Discard old events (Loại bỏ sự kiện cũ):
Bạn có thể cấu hình để loại bỏ các sự kiện đã quá cũ và không cần xử lý nữa.
⇒ Giảm độ trễ khi Lambda phải retry các batch cũ..
Ví dụ: Trong một hệ thống thời gian thực, nếu sự kiện đã quá hạn xử lý (ví dụ quá 24 giờ), bạn có thể cấu hình để bỏ qua sự kiện đó.
3.2 Giới hạn số lần retry (Retry limit):
Bạn có thể cấu hình giới hạn số lần Lambda thử lại khi gặp lỗi.
⇒ Tránh lãng phí tài nguyên vào việc retry không hiệu quả.
Ví dụ: Bạn có thể cấu hình để Lambda chỉ thử lại 5 lần cho mỗi sự kiện.
3.3 Split the batch on error (Chia nhỏ batch khi gặp lỗi):
Khi một batch lớn bị lỗi, Lambda có thể chia batch này thành nhiều batch nhỏ hơn.
⇒ Giảm khả năng lỗi xảy ra do kích thước batch quá lớn hoặc thời gian timeout Lambda.
Ví dụ: Nếu một batch gồm 100 sự kiện và Lambda gặp lỗi xử lý, bạn có thể chia batch đó thành các phần nhỏ hơn (ví dụ: 10 sự kiện mỗi batch) và thử lại từng phần nhỏ để xử lý sự kiện lỗi.
4. Destination (Điểm Đích cho Dữ Liệu Bị Bỏ Qua)
Nếu một sự kiện không thể xử lý thành công sau nhiều lần thử lại, nó có thể được gửi đến một đích (destination) khác để xử lý thêm, chẳng hạn như:
SQS (Simple Queue Service): Đưa vào hàng đợi để xử lý sau.
SNS (Simple Notification Service): Gửi thông báo về lỗi.
Lambda DLQ (Dead-Letter Queue): Đảm bảo không mất dữ liệu.
Ví dụ cấu hình Destination trong Event Source Mapping
{
"DestinationConfig": {
"OnFailure": {
"Destination": "arn:aws:sqs:us-east-1:123456789012:dlq-queue"
}
}
}
Lambda - Event Source Mapping tích hợp với SQS và SQS FIFO Queue.
1. Tổng quan về Event Source Mapping với SQS & SQS FIFO
1.1. Event Source Mapping là gì?
Event Source Mapping cho phép AWS Lambda tự động đọc tin nhắn từ Amazon SQS (Simple Queue Service) hoặc SQS FIFO (First-In-First-Out).
Lambda sẽ poll (hỏi) tin nhắn từ hàng đợi SQS, gom thành từng lô (batch) và xử lý chúng đồng bộ.
1.2. SQS vs SQS FIFO
SQS (Standard Queue): Hỗ trợ thông lượng cao, không đảm bảo thứ tự tin nhắn.
SQS FIFO (First-In-First-Out): Đảm bảo thứ tự tin nhắn, xử lý từng tin nhắn một cách có trật tự.
2. Cách Event Source Mapping Hoạt Động
2.1 Long Polling (Polling dài hạn)
Long Polling là cơ chế giúp Lambda kiểm tra SQS trong một khoảng thời gian nhất định (thay vì kiểm tra liên tục)
Lambda sử dụng Long Polling để giảm thiểu chi phí và cải thiện hiệu suất.
Lambda giữ kết nối với hàng đợi SQS lâu hơn để nhận nhiều tin nhắn trong một lần pull.
Ví dụ SQS: Bạn có một hệ thống thương mại điện tử, nơi các đơn đặt hàng của khách hàng được đưa vào hàng đợi SQS. Lambda sử dụng Event Source Mapping để kiểm tra hàng đợi này. Khi có đơn hàng mới, Lambda sẽ lấy và xử lý đơn hàng, chẳng hạn như gửi email xác nhận cho khách hàng.
2.2 Batch Size (Kích thước lô)
Bạn có thể chỉ định kích thước batch từ 1 đến 10 tin nhắn khi lấy tin nhắn từ SQS.
Lambda xử lý toàn bộ batch đồng thời.
Tại sao kích thước lô lại quan trọng?
Kích thước lô lớn hơn: Giúp bạn tối ưu hóa hiệu suất xử lý và giảm số lần gọi Lambda, nhưng nếu gặp lỗi, toàn bộ lô sẽ bị xử lý lại.
Kích thước lô nhỏ hơn: Giúp giảm thiểu số lượng tin nhắn bị ảnh hưởng khi gặp lỗi, nhưng sẽ yêu cầu nhiều lần gọi Lambda hơn.
Ví dụ Batch Size: Trong hệ thống thương mại điện tử, bạn có thể cấu hình kích thước lô là 5 tin nhắn mỗi lần. Điều này có nghĩa là mỗi lần Lambda được kích hoạt, nó sẽ lấy và xử lý tối đa 5 đơn đặt hàng cùng lúc.
2.3 Queue Visibility Timeout (Thời gian ẩn tin nhắn)
Visibility Timeout: Khoảng thời gian mà tin nhắn được ẩn khỏi các consumer khác trong khi Lambda đang xử lý nó.
Khuyến nghị: Visibility Timeout nên được đặt bằng 6 lần thời gian timeout của Lambda.
Ví dụ Visibility Timeout: Nếu thời gian chạy tối đa của hàm Lambda là 1 phút, bạn nên cấu hình Visibility Timeout của hàng đợi SQS là 6 phút. Điều này giúp tránh tình trạng tin nhắn bị xử lý lại trước khi Lambda hoàn tất công việc.
3 Sử dụng Dead Letter Queue (DLQ)
Đôi khi, tin nhắn không thể được xử lý thành công dù đã thử lại nhiều lần, lúc này, bạn nên cấu hình Dead Letter Queue (DLQ) để lưu lại các tin nhắn này và xử lý sau.
Lưu ý quan trọng:
Thiết lập DLQ trên hàng đợi SQS, không phải Lambda: Vì DLQ cho Lambda chỉ áp dụng cho asynchronous invocations, trong khi SQS sử dụng synchronous invocations.
Lambda Destination (Điểm đến Lambda): Có thể dùng thay thế DLQ để chuyển các tin nhắn lỗi đến đích khác.
Ví dụ về DLQ: Trong hệ thống xử lý đơn hàng, nếu một đơn hàng gặp lỗi nhiều lần và không thể xử lý thành công, bạn có thể gửi đơn hàng đó đến SQS DLQ. Đội ngũ kỹ thuật có thể xem lại các đơn hàng trong DLQ và xử lý chúng thủ công hoặc phân tích lý do vì sao lỗi xảy ra.
4. Luồng Xử Lý trong Hình Minh Họa
Poll (Lấy Tin Nhắn):
- Lambda sử dụng Event Source Mapping để poll tin nhắn từ hàng đợi SQS.
Batching (Gom Batch):
- Tin nhắn được gom lại thành batch (1-10 tin nhắn) và gửi đến Lambda.
Invoke Lambda:
- Lambda được gọi và xử lý batch tin nhắn đồng bộ.
Return Batch:
- Lambda xử lý xong, các tin nhắn đã xử lý được xóa khỏi SQS.
DLQ (Nếu lỗi xảy ra):
- Nếu Lambda thất bại sau nhiều lần retry, tin nhắn sẽ được chuyển vào DLQ để xử lý thủ công hoặc phân tích.
Queues & Lambda
1. Tổng Quan về Queues & AWS Lambda
Amazon SQS (Simple Queue Service) là dịch vụ hàng đợi tin nhắn có thể tích hợp với AWS Lambda để xử lý các tin nhắn trong hàng đợi một cách tự động và linh hoạt.
SQS Standard Queue: Hỗ trợ thông lượng cao, không đảm bảo thứ tự tin nhắn.
SQS FIFO Queue (First-In-First-Out): Đảm bảo tin nhắn được xử lý theo thứ tự.
AWS Lambda kết nối với SQS thông qua Event Source Mapping để:
Poll tin nhắn từ hàng đợi.
Gom tin nhắn thành batch.
Xử lý batch một cách đồng bộ.
2. Xử Lý Dữ Liệu với FIFO & Standard Queues
2.1 Xử Lý FIFO Queue (First-In, First-Out)
Đảm bảo Thứ Tự (In-order Processing): Lambda xử lý tin nhắn đúng thứ tự như chúng được gửi đến hàng đợi.
Scaling (Tự động mở rộng): Lambda tự động mở rộng để xử lý theo số lượng Message Group (nhóm tin nhắn) đang hoạt động.
Message Group: Là một nhóm tin nhắn được xác định bởi message group ID trong SQS FIFO. Các tin nhắn thuộc cùng một nhóm sẽ được xử lý lần lượt, không bị trùng lặp.
Ví dụ về hệ thống xử lý giao dịch: Trong một hệ thống xử lý giao dịch tài chính, mỗi nhóm khách hàng có thể được quản lý trong các message group riêng biệt. Điều này bảo đảm rằng các giao dịch của cùng một khách hàng sẽ được xử lý theo thứ tự, trong khi các giao dịch của khách hàng khác có thể được xử lý song song.
2.2 Xử Lý Standard Queue
Không đảm bảo thứ tự: Tin nhắn có thể được xử lý không theo thứ tự.
Tốc độ xử lý cao: Lambda mở rộng linh hoạt để xử lý nhiều batch tin nhắn đồng thời.
Ví dụ:
hệ thống gửi email marketing: Trong một chiến dịch marketing, việc gửi email không nhất thiết phải tuân theo thứ tự thời gian. Lambda có thể lấy các tin nhắn từ hàng đợi Standard Queue và gửi email nhanh nhất có thể mà không cần quan tâm đến thứ tự.
Một hàng đợi Standard chứa tin nhắn: [A, B, C, D], Lambda có thể xử lý tin nhắn theo thứ tự bất kỳ: [D, B, A, C]
3. Xử Lý Lỗi trong Queues & Lambda
3.1 Khi xảy ra lỗi
Batch Trả Về Hàng Đợi: Nếu Lambda không thể xử lý thành công batch, batch sẽ được trả về SQS như từng tin nhắn riêng lẻ.
Thay Đổi Nhóm Tin Nhắn: Khi batch được trả về, các tin nhắn có thể được gom lại thành nhóm mới và được xử lý lại với thứ tự khác nhau.
Ví dụ về batch:
tin nhắn: Một hệ thống xử lý đặt hàng đang sử dụng SQS Standard Queue. Nếu Lambda gặp lỗi khi xử lý một batch 10 đơn đặt hàng, toàn bộ các đơn hàng trong batch sẽ được trả lại hàng đợi. Lần sau khi Lambda lấy tin nhắn, các đơn hàng này có thể không nằm trong cùng một batch ban đầu.
Batch chứa tin nhắn [A, B, C] bị lỗi. Tin nhắn được trả về và chia thành các batch mới: [A], [B], [C].
3.2. Tin nhắn có thể được xử lý nhiều lần
Tình huống: Lambda có thể nhận lại tin nhắn từ hàng đợi ngay cả khi không có lỗi xảy ra.
Nguyên nhân: Visibility Timeout không được cấu hình đúng hoặc lỗi kết nối.
Ví dụ
Về tin nhắn bị xử lý hai lần: Trong một hệ thống xử lý đơn hàng, một đơn đặt hàng có thể được gửi đến Lambda hai lần nếu thời gian xử lý của Lambda vượt quá visibility timeout của hàng đợi. Điều này có thể khiến đơn hàng bị xử lý hai lần trừ khi Lambda được cấu hình để xử lý tình huống này (ví dụ: idempotent).
Tin nhắn
Order-123
được Lambda xử lý xong nhưng không kịp xác nhận với SQS. Tin nhắn này sẽ quay trở lại hàng đợi và có thể được Lambda xử lý lần nữa
3.3. Lambda tự động xóa tin nhắn sau khi xử lý thành công
Khi Lambda xử lý thành công tin nhắn, nó sẽ gửi ACK (Acknowledgment) về SQS.
Tin nhắn sau đó được xóa khỏi hàng đợi.
Ví dụ về hệ thống gửi tin nhắn SMS: Khi Lambda xử lý thành công một yêu cầu gửi SMS từ SQS Queue, yêu cầu này sẽ bị xóa khỏi hàng đợi để tránh việc gửi SMS nhiều lần.
3.2. Cấu hình Dead-Letter Queue (DLQ)
Mục đích: Lưu trữ tin nhắn không thể xử lý sau nhiều lần retry.
Cấu hình DLQ: Thực hiện trên SQS, không phải Lambda.
Ví dụ về DLQ: Trong một hệ thống thanh toán, nếu một giao dịch gặp lỗi và không thể xử lý thành công sau nhiều lần thử lại, tin nhắn giao dịch đó sẽ được gửi đến DLQ để đội ngũ kỹ thuật có thể xem xét và xử lý thủ công.
Lambda Event Mapper Scaling
Lambda Event Mapper là cơ chế giúp AWS Lambda mở rộng (scale) để xử lý dữ liệu từ các nguồn sự kiện như:
Kinesis Data Streams
DynamoDB Streams
SQS Standard Queue
SQS FIFO Queue
Mỗi nguồn sự kiện có cách mở rộng và giới hạn riêng để đảm bảo hiệu suất và tính nhất quán.
1. Kinesis Data Streams & DynamoDB Streams
1.1 Một Lambda Invocation mỗi Shard (Shard-Level Scaling)
Mỗi shard (phân đoạn) trong Kinesis hoặc DynamoDB Streams sẽ tạo một Lambda invocation.
Mỗi shard tương ứng với một instance Lambda độc lập để xử lý dữ liệu.
Thứ tự xử lý được đảm bảo cho từng shard
Ví dụ:
Có 5 shard trong Kinesis Stream.
Lambda sẽ khởi tạo 5 instance độc lập, mỗi instance xử lý dữ liệu từ một shard.
1.2 Parallelization Factor
Parallelization Factor: Cho phép Lambda xử lý nhiều batch dữ liệu đồng thời trên mỗi shard, giúp tăng tốc độ xử lý và đưa ra kết quả nhanh chóng.
Giá trị tối đa: 10 batches đồng thời trên mỗi shard.
Ví dụ:
Có 1 shard trong Kinesis.
Nếu Parallelization Factor = 5, Lambda có thể xử lý 5 batch song song từ shard đó.
Parallelization cho phép Lambda xử lý nhiều sự kiện cùng lúc từ cùng một shard
2. SQS Standard Scaling
Lambda có thể thêm 60 instance mới mỗi phút để xử lý tin nhắn trong hàng đợi SQS.
Tối đa 1,000 batch tin nhắn có thể được xử lý đồng th
Ví dụ SQS Standard: Giả sử bạn có một hệ thống đặt hàng trực tuyến và mỗi đơn đặt hàng được gửi vào SQS Standard Queue. Vào những ngày đặc biệt như Black Friday, khối lượng đơn đặt hàng tăng đột biến. Lambda sẽ tự động mở rộng quy mô để xử lý đến 1000 batches đơn hàng cùng lúc, giúp đảm bảo hệ thống không bị tắc nghẽn và các đơn hàng được xử lý nhanh chóng.
Lambda xử lý batch không cần tuân theo thứ tự.
Điều này làm cho SQS Standard rất phù hợp cho các tác vụ không yêu cầu xử lý tuần tự.
Ví dụ: Hệ thống xử lý công việc nền (background processing): Resize hình ảnh, xử lý video.
3. SQS FIFO Scaling
Tin nhắn có cùng GroupID được xử lý theo đúng thứ tự.
Mỗi GroupID sẽ tương ứng với một Lambda instance độc lập.
Lambda mở rộng theo số lượng GroupID đang hoạt động.
Nếu có 10 GroupID, Lambda có thể tạo 10 instance song song để xử lý.
Ví dụ SQS FIFO: Trong một hệ thống giao dịch tài chính, mỗi khách hàng có một GroupID riêng trong SQS FIFO Queue. Các giao dịch của từng khách hàng sẽ được xử lý theo đúng thứ tự mà chúng đến. Nếu có nhiều khách hàng thực hiện giao dịch cùng lúc, Lambda sẽ mở rộng quy mô để xử lý đồng thời các nhóm giao dịch này mà vẫn giữ nguyên thứ tự cho từng khách hàng.
Ví dụ:
Hàng đợi SQS FIFO có 3 GroupID:
Group-1
,Group-2
,Group-3
Lambda sẽ mở rộng tối đa 3 instance, mỗi instance xử lý tin nhắn từ một GroupID.
Lambda - Event and Context Objects
1. Event Object
Là gì?
Là tài liệu JSON chứa dữ liệu để Lambda Function xử lý.
Chứa thông tin từ dịch vụ gọi hàm Lambda (ví dụ: EventBridge, API Gateway, hay các sự kiện tùy chỉnh).
Được Lambda runtime chuyển đổi thành một đối tượng Python (
dict
) khi bạn làm việc với nó.
Chứa gì?
Thông tin nguồn sự kiện: Dịch vụ nào đã gọi Lambda (ví dụ:
EventBridge
,DynamoDB
).Dữ liệu chi tiết: Thông tin cụ thể của sự kiện (ví dụ: ID tài nguyên, thời gian, trạng thái).
Ví dụ về 1 EventBridge gửi một sự kiện liên quan đến việc sao lưu RDS:
{ "version": "0", "id": "fe83dc65-xml-1c5c3-2c87-81584709337", "detail-type": "RDS DB Instance Event", "source": "aws.rds", "account": "123456789012", "region": "us-east-2", "resources": ["arn:aws:rds:us-east-2:123456789012:db:rdz6xmplljbi"], "detail": { "EventCategories": ["backup"], "SourceType": "DB_INSTANCE", "Message": "Finished DB Instance backup." } }
source:
aws.rds
, cho biết nguồn gốc sự kiện đến từ dịch vụ RDS của AWS.time: Thời gian xảy ra sự kiện.
resources: ARN của tài nguyên RDS có liên quan.
detail: Phần này chứa các thông tin chi tiết, như các loại sự kiện (EventCategories) là "backup" và thông báo là "Finished DB Instance backup."
2. Context Object
Là gì?
- Cung cấp thông tin về môi trường thực thi Lambda, cấu hình hàm và các tham số phiên gọi hàm.
Chứa gì?
aws_request_id
: ID duy nhất cho mỗi lần gọi hàm Lambda.function_name
: Tên của Lambda Function.invoked_function_arn
: ARN của Lambda Function.memory_limit_in_mb
: Giới hạn bộ nhớ của hàm Lambda.log_stream_name
: Tên luồng log cho phiên gọi hàm cụ thể.client_context
: Thông tin bổ sung từ trình kích hoạt (nếu có).
{
"aws_request_id": "a3de505e-f16b-42f4-83e6-bcd2e4a73903",
"function_name": "MyFunction-AUCLS8B002F",
"invoked_function_arn": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction-AUCLS8B002F",
"function_version": "$LATEST",
"memory_limit_in_mb": "128",
"log_stream_name": "2015/10/26[$LATEST]71058852474980f22f1734d02d",
"client_context": "None"
}
Event Object:
- Trích xuất
source
vàregion
từ đối tượngevent
.
- Trích xuất
Context Object:
- Sử dụng các thuộc tính như
aws_request_id
,function_name
, vàmemory_limit_in_mb
để lấy thông tin về hàm Lambda và môi trường chạy.
- Sử dụng các thuộc tính như
Lambda - Destination
1. Tổng quan về Lambda Destinations
Là gì?
AWS Lambda Destinations là tính năng cho phép bạn xác định các điểm đích (destinations) để xử lý kết quả của các lời gọi Lambda không đồng bộ (Asynchronous Invocations) hoặc kết quả của các lô sự kiện bị loại bỏ (Event Source Mapping).
Được giới thiệu từ tháng 11/2019.
Mục đích:
Cải thiện khả năng quan sát và xử lý lỗi trong quy trình không đồng bộ.
Thay thế cho DLQ (Dead Letter Queue) trong nhiều trường hợp, nhưng bạn vẫn có thể sử dụng cả hai cùng lúc.
2. Asynchronous Invocations
📌 Asynchronous Invocations là gì?
Lambda xử lý yêu cầu và trả về kết quả sau đó mà không giữ kết nối với trình kích hoạt.
Có thể xác định các điểm đích khác nhau cho:
Sự kiện thành công: Xử lý tiếp tục nếu Lambda thành công.
Sự kiện thất bại: Chuyển kết quả lỗi đến đích chỉ định.
📌 Các điểm đích phổ biến:
Amazon SQS: Gửi thông báo lỗi hoặc thành công đến hàng đợi SQS để xử lý thêm.
Amazon SNS: Gửi thông báo qua SNS để gửi email hoặc tin nhắn.
AWS Lambda: Gọi một hàm Lambda khác để xử lý kết quả.
Amazon EventBridge: Gửi sự kiện đến EventBridge để tích hợp vào các hệ thống khác.
📌 Lưu ý quan trọng từ AWS:
Destinations được khuyến khích sử dụng thay thế cho DLQ (Dead-Letter Queue). Tuy nhiên, bạn vẫn có thể sử dụng cả hai cùng lúc.
- DLQ chỉ hỗ trợ cho những sự kiện bị lỗi, trong khi Destinations hỗ trợ cả kết quả thành công và thất bại.
📌 Ví dụ Asynchronous Invocation:
DestinationConfig:
OnSuccess:
Destination: arn:aws:sqs:us-east-1:123456789012:success-queue
OnFailure:
Destination: arn:aws:sns:us-east-1:123456789012:failure-topic
- Một Lambda xử lý hình ảnh tải lên từ Amazon S3. Sau khi Lambda tạo một bản thumbnail, nếu thành công, kết quả có thể gửi đến SQS để thông báo đã xử lý xong. Nếu thất bại, có thể gửi đến SNS để thông báo lỗi đến đội DevOps.
3. Event Source Mapping
📌 Event Source Mapping là gì?
Là cấu hình để Lambda đọc và xử lý dữ liệu từ một nguồn sự kiện như:
Amazon SQS
Amazon SNS
Amazon Kinesis
Khi nào sử dụng Event Source Mapping?
Đọc lô dữ liệu từ nguồn sự kiện.
Nếu Lambda không xử lý thành công một lô, có thể chuyển nó đến DLQ/destination khác.
📌 Các điểm đích phổ biến:
SQS: Chuyển các lô lỗi vào hàng đợi để xử lý thêm.
SNS: Gửi thông báo về các lô lỗi.
Kinesis Stream: Ghi lại dữ liệu chưa xử lý thành công.
📌 Ví dụ Event Source Mapping với Kinesis:
EventSourceMapping:
EventSourceArn: arn:aws:kinesis:us-east-1:123456789012:stream/example-stream
FunctionName: MyFunction
DestinationConfig:
OnFailure:
Destination: arn:aws:sqs:us-east-1:123456789012:failure-queue
Giải thích:
Lambda đọc dữ liệu từ example-stream trên Kinesis.
Nếu một lô không xử lý thành công, nó được gửi vào failure-queue trên SQS.
Tiêu chí | Asynchronous Invocation | Event Source Mapping |
Nguồn kích hoạt | SQS, SNS, EventBridge, Lambda | Kinesis, DynamoDB Streams |
Loại sự kiện | Không đồng bộ | Đồng bộ (Stream-based) |
Xử lý lỗi | Hỗ trợ cho sự kiện thành công và thất bại | Chỉ xử lý lô lỗi |
Điểm đích lỗi | Nhiều lựa chọn: SQS, SNS, Lambda | Chủ yếu SQS và DLQ\ |
Lambda Execution Role
1. Tổng quan về Lambda Execution Role (IAM Role)
Là gì?
Lambda Execution Role là IAM Role được cấp cho hàm Lambda để cho phép nó truy cập vào các dịch vụ và tài nguyên AWS khác.
Quyền truy cập này được kiểm soát qua các Managed Policies (Chính sách được quản lý) hoặc Inline Policies (Chính sách cài đặt trực tiếp).
IAM Role hoạt động như một danh tính có quyền cụ thể mà Lambda có thể sử dụng khi thực thi.
Tại sao cần Execution Role?
Lambda cần quyền để:
Ghi log vào Amazon CloudWatch.
Đọc dữ liệu từ Amazon SQS, Kinesis, hoặc DynamoDB Streams.
Triển khai Lambda vào VPC.
Gửi dữ liệu theo dõi đến AWS X-Ray.
2. Các Managed Policies phổ biến cho Lambda:
AWSLambdaBasicExecutionRole
Cho phép hàm Lambda ghi log vào CloudWatch Logs.
Ví dụ: Mỗi khi Lambda chạy, thông tin log như lỗi hoặc dữ liệu sẽ được ghi lại trong CloudWatch. Vai trò này cấp quyền cho Lambda thực hiện điều đó.
AWSLambdaKinesisExecutionRole
Cho phép Lambda đọc dữ liệu từ Kinesis Stream.
Ví dụ: Nếu bạn có luồng dữ liệu thời gian thực từ Kinesis và Lambda được cấu hình để xử lý dữ liệu đó, vai trò này sẽ cấp quyền để Lambda đọc luồng dữ liệu.
AWSLambdaDynamoDBExecutionRole:
Cho phép Lambda đọc dữ liệu từ DynamoDB Streams.
Ví dụ: Nếu có thay đổi trong DynamoDB (như dữ liệu mới hoặc cập nhật), DynamoDB Stream sẽ kích hoạt Lambda. Vai trò này giúp Lambda có quyền đọc dữ liệu từ Stream.
AWSLambdaSQSQueueExecutionRole:
Cho phép Lambda đọc tin nhắn từ SQS (Simple Queue Service).
Ví dụ: Một hệ thống đặt hàng có thể gửi thông tin đặt hàng vào SQS. Lambda sẽ đọc từ SQS để xử lý đơn hàng, và vai trò này giúp Lambda có quyền đọc tin nhắn từ hàng đợi SQS.
AWSLambdaVPCAccessExecutionRole:
Cho phép Lambda truy cập vào tài nguyên trong VPC (Virtual Private Cloud).
Ví dụ: Lambda có thể cần truy cập vào một cơ sở dữ liệu bên trong một VPC. Vai trò này cho phép Lambda thực hiện điều đó.
AWSXRayDaemonWriteAccess:
Cho phép Lambda gửi dữ liệu truy vết (trace data) đến AWS X-Ray.
Ví dụ: AWS X-Ray giúp bạn theo dõi và gỡ lỗi các ứng dụng phân tán. Lambda sử dụng vai trò này để gửi dữ liệu về hiệu suất và lỗi của hàm.
3. Event Source Mapping và Execution Role
Khi sử dụng Event Source Mapping (ví dụ: với Kinesis, DynamoDB Stream hoặc SQS), Lambda cần một Execution Role để đọc dữ liệu từ nguồn sự kiện. Execution Role cấp quyền cho Lambda truy cập và xử lý dữ liệu từ nguồn này.
- Ví dụ: Khi một dữ liệu mới được thêm vào DynamoDB, DynamoDB Streams sẽ kích hoạt Lambda. Vai trò Execution Role cần có quyền đọc dữ liệu từ DynamoDB Streams để Lambda có thể xử lý.
4. Best Practice – Tạo một Execution Role riêng cho mỗi hàm Lambda
AWS khuyến nghị tạo một Execution Role riêng biệt cho mỗi hàm Lambda. Điều này giúp bạn:
Kiểm soát chặt chẽ quyền truy cập của từng hàm Lambda.
Bảo mật tốt hơn: Mỗi hàm Lambda chỉ có quyền truy cập vào những tài nguyên mà nó thực sự cần.
Dễ dàng quản lý: Bạn có thể dễ dàng xác định và điều chỉnh quyền hạn của từng hàm Lambda mà không ảnh hưởng đến các hàm khác.
Ví dụ cấu hình IAM Role cho Lambda:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
],
"Resource": "arn:aws:sqs:us-east-1:123456789012:MyQueue"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:123456789012:*"
}
]
}
Resource-Based Policies
1. Resource-Based Policies là gì?
Resource-Based Policies là gì?
Resource-Based Policies là các chính sách gắn trực tiếp vào tài nguyên Lambda, thay vì IAM user hoặc IAM role.
Chúng cấp quyền truy cập vào Lambda Function cho:
Dịch vụ AWS khác (ví dụ: S3, API Gateway).
Tài khoản AWS khác (Cross-Account Access).
Tương tự như S3 Bucket Policies – cung cấp quyền dựa trên chính sách gắn vào tài nguyên.
Khi nào sử dụng Resource-Based Policies?
Cross-Account Access: Cho phép tài khoản AWS khác gọi Lambda Function.
Service Access: Cho phép dịch vụ AWS khác (như S3) gọi Lambda.
Granular Access Control: Kiểm soát chi tiết hơn quyền truy cập.
2. Sự khác biệt giữa Resource-Based Policies và IAM Policies
Tiêu chí | IAM Policy | Resource-Based Policy |
Gắn vào đâu? | IAM User, IAM Role, IAM Group | Lambda Function |
Phạm vi | Quyền cấp cho IAM Principal | Quyền cấp cho tài nguyên cụ thể |
Cross-Account Access | Không trực tiếp (cần IAM Role) | Hỗ trợ trực tiếp |
AWS service khác | Không trực tiếp | Hỗ trợ trực tiếp |
Ví dụ | Cho phép user truy cập Lambda | Cho phép S3 kích hoạt Lambda |
3. Ví dụ về cách IAM principal truy cập Lambda
Một IAM principal (có thể là một người dùng, vai trò hoặc dịch vụ) có thể truy cập Lambda theo hai cách:
Qua IAM policy: Nếu IAM policy gắn liền với người dùng hoặc vai trò có quyền gọi hàm Lambda.
- Ví dụ: Một vai trò EC2 có thể có IAM policy cho phép nó gọi hàm Lambda.
Qua Resource-Based Policy: Nếu hàm Lambda có chính sách tài nguyên cho phép principal truy cập.
- Ví dụ: Bạn có thể tạo một chính sách tài nguyên để cho phép dịch vụ Amazon S3 gọi hàm Lambda của bạn.
3. Cách hoạt động của Lambda Resource-Based Policies
📌 IAM Principal (User, Role, Service Account) có thể truy cập Lambda khi:
IAM Policy cấp quyền: Chính sách IAM gắn vào User/Role cho phép gọi Lambda.
Resource-Based Policy cấp quyền: Chính sách gắn vào Lambda Function cho phép truy cập từ tài khoản hoặc dịch vụ cụ thể.
📊 So sánh luồng quyền:
IAM Policy: "Tôi có quyền gọi Lambda này không?"
Resource-Based Policy: "Lambda này có cho phép tôi gọi không?"
📝 Ví dụ:
IAM User có quyền
lambda:InvokeFunction
→ Có thể gọi Lambda.Lambda Resource-Based Policy chỉ cho phép tài khoản AWS ID
123456789012
truy cập.
🛠️ 4. Ví dụ về Resource-Based Policy
📌 1. Cho phép một tài khoản AWS khác gọi Lambda
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:us-east-1:111111111111:function:MyFunction" } ] }
Giải thích:
Tài khoản AWS
123456789012
có thể gọi Lambda FunctionMyFunction
.Hành động được cho phép:
lambda:InvokeFunction
.
📌 2. Cho phép Amazon S3 kích hoạt Lambda Function
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:us-east-1:111111111111:function:MyFunction", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:s3:::my-bucket" } } } ] }
Giải thích:
Dịch vụ S3 được phép gọi Lambda Function
MyFunction
.Condition (Điều kiện): Chỉ các sự kiện từ S3 bucket
my-bucket
mới được phép.
🛡️ Bảo mật: Luôn sử dụng Condition
để hạn chế nguồn gọi Lambda (ví dụ: chỉ cho phép từ bucket cụ thể).
🔄 5. Cách Resource-Based Policies hoạt động với AWS Services
S3 nhận sự kiện:
- S3 Bucket
my-bucket
tải lên filefile.txt
- S3 Bucket
S3 kiểm tra Resource-Based Policy của Lambda để xem liệu nó có quyền gọi Lambda hay không:
- Lambda được cấu hình xử lý sự kiện từ
my-bucket
- Lambda được cấu hình xử lý sự kiện từ
Nếu được cho phép, S3 gọi Lambda với vai trò
s3.amazonaws.com
:
- Resource-Based Policy kiểm tra và cho phép S3 kích hoạt Lambda.
Lambda thực thi và trả về kết quả.
Environment Variables
Trong AWS Lambda, biến môi trường (environment variables) là một cách rất phổ biến để truyền các thông tin cấu hình hoặc cài đặt đến hàm Lambda mà không cần phải thay đổi mã nguồn. Điều này rất hữu ích để tùy chỉnh hành vi của hàm Lambda trong các môi trường khác nhau hoặc quản lý thông tin nhạy cảm một cách bảo mật.
1. Biến môi trường là gì?
Biến môi trường là một cặp key-value dưới dạng chuỗi (String), được cung cấp cho hàm Lambda.
Ví dụ: bạn có thể có một biến môi trường chứa URL của cơ sở dữ liệu hoặc một secret API key. Những giá trị này có thể được sử dụng trong mã Lambda của bạn.
Ví dụ đơn giản:
python
Copy code
import os
def lambda_handler(event, context):
# Truy cập biến môi trường
db_url = os.getenv('DATABASE_URL')
print(f"Database URL: {db_url}")
Trong ví dụ này, bạn có thể đặt giá trị biến môi trường DATABASE_URL
trong cấu hình Lambda của mình. Hàm Lambda sau đó sẽ truy cập giá trị này mà không cần viết cứng vào mã nguồn.
2. Lợi ích của việc sử dụng biến môi trường
Điều chỉnh hành vi hàm Lambda mà không cần thay đổi mã: Bạn có thể thay đổi cấu hình (ví dụ, thông tin cơ sở dữ liệu) mà không cần thay đổi mã nguồn và triển khai lại hàm.
Truyền thông tin bí mật: Bạn có thể sử dụng biến môi trường để lưu trữ các thông tin nhạy cảm như mật khẩu, khóa API, token, v.v.
Bảo mật: Các biến môi trường có thể được mã hóa bằng KMS (Key Management Service), đảm bảo rằng dữ liệu nhạy cảm được bảo vệ tốt.
3. Biến môi trường hệ thống do Lambda tự thêm vào
Lambda tự động thêm một số biến môi trường hệ thống vào hàm của bạn. Đây là các biến mà bạn có thể không cần phải tự cấu hình, ví dụ như:
AWS_REGION: Vùng AWS nơi hàm Lambda đang chạy.
AWS_LAMBDA_FUNCTION_NAME: Tên của hàm Lambda.
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: Kích thước bộ nhớ (memory size) của hàm Lambda.
Ví dụ:
python
Copy code
import os
def lambda_handler(event, context):
function_name = os.getenv('AWS_LAMBDA_FUNCTION_NAME')
print(f"This Lambda function name is {function_name}")
Trong ví dụ này, Lambda tự động thêm biến AWS_LAMBDA_FUNCTION_NAME
, bạn có thể truy cập nó để biết tên của hàm đang chạy.
4. Sử dụng biến môi trường để lưu trữ thông tin bí mật
Nếu bạn cần lưu trữ các secrets như mật khẩu, khóa API trong biến môi trường, bạn có thể mã hóa chúng bằng KMS (Key Management Service).
- KMS Encryption: Bạn có thể sử dụng khóa mã hóa do Lambda quản lý hoặc tạo Customer Managed Key (CMK) của riêng bạn. Khi một biến môi trường được mã hóa, nó sẽ được giải mã tự động trước khi hàm Lambda chạy.
Ví dụ cách mã hóa secrets với Lambda:
Trong phần cấu hình Lambda, khi thêm biến môi trường, bạn chọn sử dụng mã hóa KMS.
Secrets sẽ được lưu trữ ở dạng mã hóa và chỉ được giải mã trong môi trường Lambda khi cần thiết.
5. Lưu ý khi sử dụng Lambda Environment Variables
Quản lý thông tin nhạy cảm: Khi lưu trữ secrets, hãy chắc chắn mã hóa các biến môi trường bằng KMS.
Giới hạn kích thước: Có giới hạn về số lượng biến môi trường và kích thước dữ liệu mà bạn có thể sử dụng cho một hàm Lambda. Tổng số dữ liệu trong biến môi trường không được vượt quá 4KB.
Khả năng kiểm soát: Mặc dù rất tiện lợi, nhưng hãy hạn chế lưu trữ các thông tin quá nhạy cảm nếu không thực sự cần thiết. Đảm bảo rằng các secrets được bảo vệ tốt và chỉ những ai cần biết mới có quyền truy cập.
6. Tổng kết
Biến môi trường là cách hữu ích để truyền thông tin cấu hình mà không cần thay đổi mã nguồn.
Chúng giúp bạn quản lý hàm Lambda linh hoạt hơn trong nhiều môi trường khác nhau (development, production).
Bạn có thể mã hóa secrets để bảo vệ thông tin nhạy cảm và sử dụng KMS để giải mã chúng khi hàm Lambda chạy.
Trong AWS Lambda, việc theo dõi và ghi log là một phần quan trọng để quản lý và giám sát các hàm của bạn. Điều này giúp bạn hiểu rõ hơn về cách hàm Lambda của mình hoạt động, giúp phát hiện các vấn đề, cải thiện hiệu năng, và duy trì tính khả dụng của hệ thống.
1. CloudWatch Logs
CloudWatch Logs là nơi mà AWS Lambda ghi lại tất cả các log của các lần thực thi hàm. Mỗi lần hàm Lambda chạy, log chi tiết sẽ được ghi lại và lưu trữ trong CloudWatch Logs. Những log này bao gồm thông tin như:
Thời gian bắt đầu và kết thúc của lần thực thi
Các lỗi xảy ra trong quá trình thực thi
Các kết quả và thông tin bạn tự ghi lại bằng
print()
hoặcconsole.log()
Ví dụ: Trong hàm Lambda, bạn có thể ghi log như sau:
python
Copy code
def lambda_handler(event, context):
print("Hàm Lambda đã được gọi")
return "Hello World!"
Thông báo "Hàm Lambda đã được gọi"
sẽ được ghi lại trong CloudWatch Logs.
Lưu ý về quyền (IAM Policy):
Hàm Lambda cần có quyền ghi log vào CloudWatch Logs. Để làm được điều này, hàm Lambda cần có IAM Role với chính sách (policy) cho phép ghi vào CloudWatch Logs.
Ví dụ về chính sách IAM cho phép ghi log:
json
Copy code
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
Điều này đảm bảo rằng Lambda có quyền tạo log group, log stream và ghi các log event.
2. CloudWatch Metrics (Số liệu giám sát)
Bên cạnh việc ghi log, Lambda còn tự động tạo ra các số liệu (metrics), được hiển thị trong AWS CloudWatch Metrics. Các số liệu này cung cấp thông tin chi tiết về hoạt động của hàm Lambda, bao gồm:
Invocations: Số lần hàm Lambda được gọi.
Durations: Thời gian thực thi của hàm Lambda.
Concurrent Executions: Số lần thực thi đồng thời của hàm Lambda.
Error count: Số lỗi xảy ra trong khi thực thi hàm.
Success Rates: Tỷ lệ thành công của các lần gọi hàm.
Throttles: Số lần hàm Lambda bị giới hạn do vượt quá số lượng thực thi đồng thời cho phép.
Async Delivery Failures: Số lần thất bại khi xử lý các yêu cầu bất đồng bộ (asynchronous).
Iterator Age: Dùng cho các nguồn dữ liệu stream như Kinesis và DynamoDB Streams, chỉ ra độ trễ của dữ liệu được xử lý.
Ví dụ sử dụng CloudWatch Metrics:
Bạn có thể sử dụng các số liệu này để theo dõi hiệu suất của Lambda và thiết lập CloudWatch Alarms. Ví dụ, nếu thời gian thực thi Lambda vượt quá một ngưỡng nhất định, bạn có thể nhận thông báo (notification) hoặc tự động thực hiện các hành động sửa chữa.
- Ví dụ: Bạn có thể tạo một cảnh báo (alarm) nếu số lượng Errors vượt quá 5 trong 1 giờ. Điều này giúp bạn phát hiện các vấn đề trong hàm Lambda và xử lý nhanh chóng.
3. Một số lưu ý bổ sung
Để giám sát hiệu quả, hãy đảm bảo bạn theo dõi thường xuyên các số liệu quan trọng như Durations (thời gian thực thi), Throttles (giới hạn), và Errors (lỗi).
Nếu hàm Lambda của bạn xử lý khối lượng công việc lớn (như từ Kinesis hoặc DynamoDB Streams), bạn cần chú ý đến chỉ số Iterator Age để đảm bảo không có độ trễ lớn trong quá trình xử lý dữ liệu.
4. Tổng kết
CloudWatch Logs giúp bạn xem chi tiết về các log của hàm Lambda, trong khi CloudWatch Metrics cung cấp số liệu giám sát giúp bạn hiểu rõ hơn về hiệu suất và tính khả dụng của hàm Lambda. Cả hai công cụ này đều rất quan trọng trong việc vận hành và tối ưu hóa hệ thống Lambda của bạn.
AWS X-Ray là một công cụ giúp theo dõi (trace) và phân tích cách các dịch vụ của bạn (bao gồm Lambda) tương tác với nhau. Điều này cực kỳ hữu ích khi bạn cần tối ưu hóa và debug các ứng dụng serverless.
1. Kích hoạt Tracing trong Lambda (Active Tracing)
Khi bạn sử dụng X-Ray với Lambda, bạn cần kích hoạt Active Tracing trong cấu hình của Lambda. Khi Active Tracing được bật, AWS Lambda sẽ tự động chạy một daemon X-Ray, giúp thu thập và ghi lại các thông tin theo dõi về thời gian thực thi của hàm.
Ví dụ: Bạn có thể kích hoạt tính năng này trong phần cấu hình của hàm Lambda khi tạo hoặc chỉnh sửa hàm, hoặc bạn có thể sử dụng AWS CLI:
bash
Copy code
aws lambda update-function-configuration --function-name my-function --tracing-config Mode=Active
Khi Active Tracing được bật, Lambda sẽ tự động tạo các phân đoạn (segments) trong X-Ray cho mỗi lần thực thi hàm.
2. Sử dụng AWS X-Ray SDK trong mã nguồn
Để có thể theo dõi sâu hơn cách hàm của bạn hoạt động, bạn có thể sử dụng AWS X-Ray SDK trong mã nguồn của mình. SDK này cung cấp nhiều công cụ để bạn có thể ghi lại các phân đoạn chi tiết hơn về các tác vụ bên trong hàm Lambda.
Ví dụ: Bạn có thể theo dõi thời gian thực thi của một đoạn mã cụ thể bên trong hàm Lambda:
python
Copy code
import aws_xray_sdk.core as xray
def lambda_handler(event, context):
with xray.recorder.in_segment('ProcessSegment') as segment:
# Đoạn mã mà bạn muốn theo dõi chi tiết
print("Xử lý...")
return "Done"
Đoạn mã trên sử dụng X-Ray SDK để tạo ra một segment riêng cho phần xử lý và ghi lại thời gian thực thi của nó.
3. Xác định đúng IAM Role cho Lambda
Hàm Lambda của bạn cần có IAM Execution Role với chính sách cho phép Lambda ghi dữ liệu vào X-Ray. Chính sách được sử dụng là AWSXRayDaemonWriteAccess, cho phép hàm Lambda gửi dữ liệu tới X-Ray daemon.
Ví dụ về chính sách IAM cho phép Lambda ghi dữ liệu vào X-Ray:
json
Copy code
{
"Effect": "Allow",
"Action": [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
],
"Resource": "*"
}
Điều này đảm bảo rằng Lambda có quyền ghi thông tin theo dõi vào AWS X-Ray.
4. Các biến môi trường liên quan đến X-Ray
Lambda sử dụng một số biến môi trường (environment variables) để giao tiếp với X-Ray daemon và cấu hình cách theo dõi được thực hiện. Một số biến quan trọng bao gồm:
XAMZN_TRACE_ID: Biến này chứa thông tin về trace ID hiện tại. Bạn có thể sử dụng biến này để theo dõi yêu cầu cụ thể hoặc khi debug.
AWS_XRAY_CONTEXT_MISSING: Đây là cấu hình mặc định để ghi lỗi nếu thiếu ngữ cảnh X-Ray.
AWS_XRAY_DAEMON_ADDRESS: Địa chỉ của X-Ray Daemon (gồm IP và port), nơi mà các hàm Lambda gửi dữ liệu theo dõi.
Ví dụ: Bạn có thể truy cập XAMZN_TRACE_ID trong mã nguồn để theo dõi trace hiện tại:
python
Copy code
import os
def lambda_handler(event, context):
trace_id = os.getenv('_X_AMZN_TRACE_ID')
print(f"Trace ID hiện tại: {trace_id}")
Kết quả log sẽ ghi lại Trace ID của lần gọi Lambda, giúp bạn có thể dễ dàng tìm kiếm trong AWS X-Ray console.
5. Ví dụ hoàn chỉnh về Tracing
Giả sử bạn có một hàm Lambda nhận và xử lý dữ liệu từ S3, bạn có thể bật X-Ray tracing để theo dõi toàn bộ quy trình:
Bước 1: Kích hoạt Active Tracing trong cấu hình Lambda.
Bước 2: Sử dụng X-Ray SDK để ghi lại thời gian thực thi của từng bước.
python
Copy code
import boto3
import aws_xray_sdk.core as xray
s3 = boto3.client('s3')
def lambda_handler(event, context):
with xray.recorder.in_segment('S3ProcessingSegment'):
# Lấy dữ liệu từ S3
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
response = s3.get_object(Bucket=bucket, Key=key)
# Xử lý dữ liệu
print(f"Đang xử lý file {key} từ bucket {bucket}")
return "Xử lý hoàn tất"
Hàm trên sử dụng X-Ray SDK để ghi lại thời gian thực thi của việc xử lý tệp từ S3.
6. Tổng kết
AWS X-Ray là công cụ mạnh mẽ giúp bạn theo dõi và debug các hàm Lambda của mình.
Bạn cần đảm bảo Active Tracing được bật trong cấu hình Lambda và hàm của bạn có quyền sử dụng X-Ray thông qua IAM Role.
Sử dụng AWS X-Ray SDK để ghi lại chi tiết hơn về từng phân đoạn trong mã nguồn của bạn.
Thông qua việc sử dụng các biến môi trường, bạn có thể theo dõi chính xác trace ID và cấu hình theo dõi cho hàm Lambda của mình.
Customization At The Edge với AWS Lambda@Edge và CloudFront Functions
1. Khái niệm về Edge Function và Tùy chỉnh tại Edge
Edge Function là các đoạn mã bạn viết và gắn vào các phân phối (distributions) Amazon CloudFront, nhằm thực thi logic ngay tại vị trí gần nhất với người dùng. Điều này giúp giảm độ trễ và tăng tốc độ xử lý yêu cầu từ người dùng.
Customization at the Edge là việc tùy chỉnh và xử lý logic ngay tại các điểm biên (edge locations) của CloudFront, thay vì tại một máy chủ trung tâm, giúp tăng hiệu suất ứng dụng.
Ví dụ: Khi người dùng từ Việt Nam truy cập vào một trang web, thay vì yêu cầu được chuyển đến một server ở Mỹ, CloudFront có thể xử lý yêu cầu ngay tại các edge location ở khu vực gần Việt Nam nhất (ví dụ: Singapore), giúp giảm độ trễ.
2. Hai loại chức năng tại Edge: CloudFront Functions và Lambda@Edge
AWS cung cấp hai loại Edge Functions để triển khai logic tại các vị trí gần người dùng:
CloudFront Functions: Đây là loại hàm siêu nhẹ, phù hợp cho các tác vụ đơn giản như xác thực, tùy chỉnh URL, và sửa đổi các headers HTTP. Các hàm này được thiết kế để xử lý hàng triệu yêu cầu trong thời gian cực ngắn với độ trễ thấp.
Ví dụ: Bạn có thể sử dụng CloudFront Function để thêm hoặc xóa các headers trước khi chuyển yêu cầu đến server gốc (origin).
Lambda@Edge: Đây là một phiên bản của AWS Lambda được triển khai và chạy tại các edge locations của CloudFront. Lambda@Edge có thể xử lý các tác vụ phức tạp hơn như chuyển đổi nội dung, tạo trang động, hoặc xử lý yêu cầu của người dùng dựa trên địa lý.
Ví dụ: Bạn có thể dùng Lambda@Edge để thay đổi nội dung trang web hiển thị cho người dùng dựa trên vị trí địa lý. Nếu người dùng truy cập từ Việt Nam, bạn có thể hiển thị nội dung bằng tiếng Việt, trong khi nếu người dùng đến từ Mỹ, nội dung có thể được hiển thị bằng tiếng Anh.
3. Không cần quản lý máy chủ và triển khai toàn cầu
Khi sử dụng CloudFront Functions hoặc Lambda@Edge, bạn không cần phải quản lý máy chủ. Tất cả các logic của bạn sẽ được triển khai tự động trên hàng trăm edge locations của CloudFront trên toàn cầu. AWS tự động đảm bảo rằng mã của bạn sẽ chạy tại các vị trí gần người dùng nhất, giảm thiểu độ trễ tối đa.
4. Tùy chỉnh nội dung CDN (Content Delivery Network)
Một trong những ứng dụng phổ biến của Edge Functions là tùy chỉnh nội dung được phân phối qua mạng CDN của CloudFront. Bạn có thể thay đổi các yếu tố như URL, headers, hoặc nội dung trang web mà không cần thay đổi bất kỳ thứ gì trên server gốc.
Ví dụ: Một trang web thương mại điện tử có thể sử dụng CloudFront và Lambda@Edge để tự động chuyển đổi ngôn ngữ và tiền tệ dựa trên quốc gia của người dùng. Nếu người dùng từ Pháp truy cập vào, bạn có thể hiển thị giá sản phẩm bằng Euro và nội dung bằng tiếng Pháp.
5. Tính chi phí hợp lý (Pay only for what you use)
Bạn chỉ phải trả chi phí cho những gì bạn sử dụng. Cả CloudFront Functions và Lambda@Edge đều tính phí dựa trên số lượng yêu cầu mà các hàm của bạn xử lý. Điều này giúp giảm thiểu chi phí khi bạn không cần sử dụng một lượng tài nguyên lớn liên tục.
6. Hoàn toàn Serverless (Fully Serverless)
Với cả hai loại chức năng này, bạn không phải quản lý bất kỳ máy chủ nào. AWS sẽ tự động quản lý các tài nguyên cơ sở hạ tầng cần thiết để chạy các hàm của bạn.
Ví dụ Thực tế
CloudFront Function: Một ví dụ phổ biến là sử dụng chức năng này để tự động chuyển hướng người dùng dựa trên URL. Ví dụ: nếu người dùng truy cập vào
example.com/home
, bạn có thể dùng CloudFront Function để chuyển hướng đếnexample.com/vi/home
nếu họ đến từ Việt Nam.Lambda@Edge: Một ví dụ khác là sử dụng Lambda@Edge để tùy chỉnh caching. Bạn có thể định nghĩa các quy tắc cho việc lưu trữ nội dung tĩnh dựa trên các yêu cầu cụ thể của người dùng, như địa chỉ IP hoặc quốc gia.
Kết luận
CloudFront Functions: Tốt cho các tác vụ đơn giản, yêu cầu thời gian xử lý nhanh.
Lambda@Edge: Tốt cho các tác vụ phức tạp hơn như xử lý dựa trên ngữ cảnh người dùng hoặc địa lý.
Lambda by Default là gì?
Mặc định, các hàm (functions) Lambda của bạn sẽ được chạy bên ngoài VPC của riêng bạn, tức là trong VPC được quản lý bởi AWS. Điều này có nghĩa rằng Lambda mặc định không thể truy cập vào các tài nguyên nội bộ (private) trong VPC của bạn như:
RDS (Cơ sở dữ liệu quan hệ Amazon)
ElastiCache
Internal Load Balancer (ELB nội bộ)
Điều này có thể là một trở ngại nếu ứng dụng của bạn cần truy cập vào các tài nguyên riêng tư trong mạng của bạn.
Ví dụ thực tế từ ảnh minh họa
1. Public WWW (hoạt động bình thường)
Khi Lambda của bạn được triển khai mặc định bên ngoài VPC, nó có thể truy cập vào các dịch vụ công khai, ví dụ như:
DynamoDB: Một dịch vụ cơ sở dữ liệu NoSQL được cung cấp bởi AWS mà không yêu cầu Lambda phải nằm trong VPC của bạn.
S3 (không có trong hình nhưng cũng là một ví dụ): Lambda có thể dễ dàng truy cập vào các bucket S3.
Trong hình minh họa, yêu cầu từ Lambda đến DynamoDB hoạt động bình thường vì cả hai đều nằm bên ngoài VPC riêng tư của bạn.
2. Private RDS (không hoạt động)
Tuy nhiên, nếu Lambda của bạn muốn truy cập vào một cơ sở dữ liệu RDS nằm trong VPC riêng tư, yêu cầu này sẽ không thành công. Lý do là vì Lambda, mặc định, không có quyền truy cập vào mạng nội bộ trong VPC của bạn.
Vậy làm thế nào để Lambda có thể truy cập tài nguyên trong VPC?
Nếu bạn muốn Lambda truy cập các tài nguyên nội bộ như RDS hoặc ElastiCache nằm trong VPC, bạn cần cấu hình cho Lambda hoạt động bên trong VPC của bạn. Dưới đây là các bước cơ bản:
Chọn VPC khi tạo hoặc cập nhật Lambda Function:
Khi tạo hoặc cập nhật Lambda, bạn cần chỉ định rằng hàm này sẽ chạy trong một VPC cụ thể. Trong AWS Console, bạn sẽ chọn:
VPC ID: Đây là mạng mà Lambda sẽ chạy trong đó.
Subnets: Bạn có thể chọn các subnet riêng tư trong VPC của mình (nếu bạn muốn Lambda không có truy cập trực tiếp ra ngoài Internet).
Security Groups: Bạn cần tạo một nhóm bảo mật (security group) cho phép Lambda có quyền truy cập đến tài nguyên bạn muốn, ví dụ như cho phép Lambda kết nối đến cơ sở dữ liệu RDS qua cổng 3306 (đối với MySQL).
Cân nhắc về mạng NAT (Network Address Translation):
Nếu Lambda của bạn cần truy cập Internet (ví dụ: gửi yêu cầu đến một API bên ngoài hoặc tải dữ liệu từ S3), bạn cần phải có một NAT Gateway trong VPC.
Tại sao cần NAT? Vì khi bạn chạy Lambda trong một subnet riêng tư (private subnet), subnet này thường không có quyền truy cập trực tiếp ra Internet. Bạn cần cấu hình một NAT Gateway trong một public subnet để cho phép Lambda gửi các yêu cầu ra bên ngoài.
Ví dụ thực tế
Giả sử bạn có một ứng dụng web nơi người dùng có thể đăng ký và dữ liệu của họ được lưu trữ trong RDS. Bạn có một hàm Lambda để xử lý yêu cầu đăng ký và lưu dữ liệu vào RDS.
Tình huống mặc định (Không có VPC):
- Lambda của bạn có thể xử lý các yêu cầu công khai như gửi email xác nhận hoặc ghi dữ liệu vào DynamoDB. Nhưng khi Lambda cố gắng kết nối với cơ sở dữ liệu RDS, nó sẽ gặp lỗi vì không thể truy cập vào VPC.
Tình huống với VPC:
- Bạn cần cấu hình Lambda để chạy trong VPC của bạn, chọn subnet và security group có quyền truy cập vào RDS. Khi đó, Lambda có thể kết nối trực tiếp tới RDS và lưu dữ liệu người dùng.
Một số lưu ý quan trọng khi sử dụng Lambda trong VPC:
Thời gian khởi động (Cold Start):
- Khi Lambda được chạy trong VPC, thời gian khởi động có thể dài hơn (do thời gian thiết lập network interface – ENI). Điều này có thể gây ra độ trễ trong lần gọi đầu tiên, thường gọi là cold start.
Quyền truy cập:
- Bạn cần chắc chắn rằng Lambda có IAM Role phù hợp để truy cập tài nguyên trong VPC và các dịch vụ AWS khác (như RDS hoặc S3).
Chi phí:
- Việc sử dụng NAT Gateway có thể tăng chi phí, vì NAT Gateway có phí hoạt động dựa trên lượng dữ liệu được truyền qua nó.
Tóm lại
Mặc định, các hàm Lambda chạy ngoài VPC và không thể truy cập các tài nguyên nội bộ như RDS hoặc ElastiCache. Để khắc phục điều này, bạn cần cấu hình Lambda chạy trong VPC và thiết lập các mạng con (subnet), nhóm bảo mật (security group) phù hợp. Điều này giúp bạn có thể mở rộng khả năng của Lambda để truy cập vào các tài nguyên quan trọng trong VPC của bạn, nhưng bạn cũng cần chú ý về các yếu tố như cold start và chi phí NAT Gateway.
Triển khai Lambda trong VPC (Lambda in VPC)
1. Cấu hình Lambda để chạy trong VPC
Khi bạn triển khai một hàm Lambda trong VPC, bạn phải cấu hình các thông số sau:
VPC ID: Đây là ID của mạng VPC nơi Lambda của bạn sẽ chạy.
Subnets (Mạng con): Bạn cần chọn các subnet trong VPC, có thể là private subnet nếu bạn muốn Lambda không có quyền truy cập trực tiếp ra Internet.
Security Groups (Nhóm bảo mật): Bạn phải chỉ định Security Group để kiểm soát quyền truy cập của Lambda đến các tài nguyên khác trong VPC.
Khi bạn thiết lập Lambda để chạy trong VPC:
- Lambda sẽ tạo ra một Elastic Network Interface (ENI) trong subnet mà bạn đã chỉ định. ENI này là cầu nối giúp Lambda giao tiếp với các tài nguyên khác trong VPC (như cơ sở dữ liệu RDS).
Ví dụ minh họa từ hình:
Lambda Security Group: Nhóm bảo mật cho phép Lambda giao tiếp với tài nguyên khác như RDS.
RDS Security Group: Nhóm bảo mật cho phép RDS chấp nhận kết nối từ ENI của Lambda.
2. Vai trò quyền truy cập (AWSLambdaVPCAccessExecutionRole)
Để Lambda có thể tương tác với tài nguyên trong VPC, bạn cần gán cho nó một vai trò (IAM Role) có quyền AWSLambdaVPCAccessExecutionRole. Vai trò này cho phép Lambda tạo và quản lý các ENI cần thiết để kết nối với VPC.
Lambda trong VPC – Truy cập Internet (Lambda in VPC – Internet Access)
1. Lambda trong VPC không có truy cập Internet mặc định
Khi Lambda được triển khai trong VPC, mặc định nó không có quyền truy cập Internet. Điều này là do các subnet bạn chọn có thể không được cấu hình để truy cập ra bên ngoài, ví dụ:
Private Subnet: Thường không có quyền truy cập Internet.
Public Subnet: Có thể có quyền truy cập Internet thông qua Internet Gateway (IGW).
2. Cách thiết lập Lambda để có quyền truy cập Internet
Không có Internet mặc định: Ngay cả khi bạn triển khai Lambda trong public subnet, điều đó không có nghĩa là Lambda có IP công cộng hoặc truy cập Internet. Điều này có nghĩa bạn cần thiết lập cụ thể hơn để Lambda có thể kết nối ra bên ngoài.
Có hai cách chính để Lambda trong private subnet có thể truy cập Internet:
Sử dụng NAT Gateway hoặc NAT Instance:
NAT (Network Address Translation) Gateway hoặc NAT Instance sẽ cho phép Lambda trong private subnet gửi yêu cầu ra ngoài Internet (ví dụ: đến API bên ngoài) thông qua Internet Gateway.
Ví dụ từ hình: Lambda gửi yêu cầu ra ngoài qua NAT Gateway được cấu hình trong Public Subnet.
Sử dụng VPC Endpoints:
Nếu Lambda của bạn cần truy cập các dịch vụ AWS khác như DynamoDB hoặc S3, bạn có thể thiết lập VPC Endpoints. Điều này cho phép Lambda truy cập các dịch vụ này một cách riêng tư mà không cần thông qua Internet.
Trong hình, Lambda trong private subnet có thể kết nối đến DynamoDB thông qua VPC Endpoint, không cần truy cập Internet.
3. Các tình huống cụ thể
Truy cập DynamoDB qua Endpoint: Lambda có thể sử dụng VPC Endpoint để kết nối với DynamoDB mà không cần NAT Gateway.
Truy cập API bên ngoài: Nếu Lambda cần gửi yêu cầu tới API bên ngoài (ví dụ: một dịch vụ thanh toán), bạn cần cấu hình NAT Gateway để cho phép Lambda trong private subnet kết nối ra ngoài thông qua Internet Gateway (IGW).
Ví dụ cụ thể trong thực tế
Giả sử bạn có một ứng dụng web nơi người dùng đăng ký thông qua một form. Lambda của bạn sẽ thực hiện các nhiệm vụ sau:
Lưu dữ liệu đăng ký vào RDS (Cơ sở dữ liệu quan hệ trong VPC):
Lambda cần chạy trong private subnet để kết nối đến RDS.
Bạn phải tạo ENI và chỉ định security group cho phép Lambda kết nối tới RDS qua cổng 3306 (đối với MySQL).
Gửi yêu cầu xác nhận đến API bên ngoài:
Lambda cần quyền truy cập Internet để gửi yêu cầu tới một API bên ngoài (ví dụ: gửi email xác nhận).
Bạn cần thiết lập một NAT Gateway trong public subnet để Lambda có thể gửi yêu cầu ra ngoài Internet.
Ghi log vào DynamoDB:
- Bạn có thể thiết lập một VPC Endpoint cho DynamoDB để Lambda trong VPC có thể ghi dữ liệu log vào DynamoDB mà không cần thông qua Internet.
Tóm lại
Lambda trong VPC: Khi bạn triển khai Lambda trong VPC, nó có thể truy cập tài nguyên nội bộ trong VPC (như RDS) thông qua ENI và security group.
Truy cập Internet: Lambda không có quyền truy cập Internet mặc định khi ở trong VPC, nhưng bạn có thể sử dụng NAT Gateway hoặc VPC Endpoints để cấp quyền truy cập phù hợp với từng tình huống.
Chi phí và cấu hình: Việc sử dụng NAT Gateway có thể gia tăng chi phí, vì vậy việc lựa chọn giữa NAT và VPC Endpoints cần dựa trên mục tiêu ứng dụng của bạn.
1. RAM (Bộ nhớ)
Bạn có thể cấu hình bộ nhớ RAM cho Lambda từ 128 MB đến 10 GB. Điều thú vị ở đây là:
- Bộ nhớ được tăng dần theo từng mức 1 MB. Điều này có nghĩa bạn có thể điều chỉnh RAM một cách linh hoạt tùy vào yêu cầu của ứng dụng.
Cách RAM ảnh hưởng đến vCPU (Central Processing Unit)
Thêm RAM, thêm CPU Credits:
- Khi bạn tăng RAM, bạn cũng sẽ được thêm các tài nguyên CPU (vCPU). Điều này có nghĩa rằng nếu ứng dụng của bạn đòi hỏi tính toán nhiều (tính toán nặng, ví dụ như xử lý dữ liệu lớn hoặc mã hóa), việc tăng RAM sẽ giúp hàm Lambda chạy nhanh hơn.
1,792 MB = 1 vCPU:
- Khi bạn cấu hình RAM ở mức 1,792 MB, bạn sẽ có được một vCPU hoàn chỉnh. Điều này rất quan trọng nếu ứng dụng của bạn cần CPU mạnh mẽ để xử lý các tác vụ nặng.
Sau 1,792 MB, Lambda có thể sử dụng nhiều hơn một CPU:
- Nếu bạn tăng RAM lên trên 1,792 MB, Lambda sẽ có khả năng sử dụng nhiều hơn một CPU (lên đến 6 vCPU). Tuy nhiên, để tận dụng hiệu quả nhiều CPU, mã của bạn cần được thiết kế với khả năng đa luồng (multi-threading).
Khi nào cần tăng RAM?
Nếu ứng dụng của bạn bị hạn chế bởi CPU (tức là cần nhiều sức mạnh tính toán), hãy cân nhắc tăng RAM.
- Ví dụ: Một hàm Lambda phải xử lý hàng triệu bản ghi từ một tệp log lớn. Nếu chỉ sử dụng 128 MB RAM, thời gian xử lý có thể rất chậm. Tuy nhiên, nếu bạn tăng RAM lên 1,792 MB hoặc hơn, hàm sẽ chạy nhanh hơn đáng kể nhờ việc sử dụng nhiều CPU hơn.
2. Timeout (Thời gian chờ)
Thời gian chờ mặc định (default timeout) là 3 giây.
Thời gian chờ tối đa (maximum timeout) là 900 giây (tương đương với 15 phút).
Khi nào cần điều chỉnh timeout?
- Nếu tác vụ của bạn cần nhiều thời gian để hoàn thành, hãy tăng thời gian chờ. Mặc định, nếu hàm Lambda của bạn vượt quá thời gian chờ mà bạn đã thiết lập, AWS sẽ dừng hàm và nó sẽ bị xem là thất bại.
Ví dụ:
Giả sử bạn có một hàm Lambda đọc dữ liệu từ một cơ sở dữ liệu lớn và phải mất 5 phút để hoàn thành tác vụ. Nếu bạn không thay đổi thời gian chờ và để mặc định là 3 giây, hàm sẽ bị dừng trước khi hoàn thành.
Trong trường hợp này, bạn cần tăng timeout lên một giá trị hợp lý (ví dụ: 300 giây = 5 phút) để hàm có đủ thời gian hoàn thành tác vụ của nó.
Ví dụ cụ thể về cách cấu hình RAM và Timeout cho Lambda
Tình huống 1: Xử lý ảnh tải lên từ người dùng
Bạn có một ứng dụng cho phép người dùng tải ảnh lên và bạn sử dụng Lambda để:
Resize (thay đổi kích thước ảnh).
Tạo thumbnail.
Cấu hình RAM: Vì việc xử lý ảnh đòi hỏi CPU để resize ảnh, bạn có thể cần tăng RAM để có thêm vCPU. Giả sử ảnh có độ phân giải cao, bạn có thể tăng RAM lên 1,792 MB để có một vCPU mạnh mẽ giúp xử lý nhanh hơn.
Timeout: Việc xử lý ảnh thường hoàn thành trong vài giây, vì vậy bạn có thể giữ thời gian chờ mặc định là 3 giây. Tuy nhiên, nếu ứng dụng của bạn xử lý các ảnh lớn hơn, bạn có thể cần tăng timeout lên 10 giây.
Tình huống 2: Phân tích dữ liệu lớn
Giả sử bạn có một hàm Lambda cần phân tích một tệp dữ liệu lớn từ S3 (ví dụ: một tệp CSV với hàng triệu bản ghi).
Cấu hình RAM: Do việc phân tích dữ liệu đòi hỏi nhiều sức mạnh tính toán, bạn nên tăng RAM lên 3,000 MB hoặc hơn để Lambda có thể sử dụng nhiều CPU hơn.
Timeout: Vì quá trình này có thể mất thời gian lâu hơn (ví dụ: 10 phút), bạn cần tăng timeout lên 600 giây để đảm bảo rằng Lambda có đủ thời gian để hoàn thành phân tích.
Kết luận
RAM và vCPU: Tăng RAM không chỉ tăng bộ nhớ mà còn tăng CPU credits cho Lambda. Khi đạt đến 1,792 MB RAM, bạn có một vCPU hoàn chỉnh và nếu tăng thêm, bạn có thể tận dụng nhiều CPU hơn, điều này cực kỳ hữu ích cho các ứng dụng nặng về tính toán.
Timeout: Mặc định là 3 giây, nhưng bạn có thể tăng tối đa đến 15 phút, tùy thuộc vào yêu cầu của tác vụ. Điều chỉnh timeout hợp lý giúp đảm bảo rằng Lambda có đủ thời gian để hoàn thành mà không bị dừng giữa chừng.
Lambda Execution Context (ngữ cảnh thực thi của Lambda), là một khái niệm rất quan trọng khi làm việc với AWS Lambda, đặc biệt khi bạn tối ưu hóa hiệu suất hàm Lambda của mình. Mình sẽ giải thích chi tiết về khái niệm này và cung cấp các ví dụ để bạn hiểu rõ hơn, hỗ trợ tốt cho việc chuẩn bị thi AWS Certified Developer – Associate.
Lambda Execution Context là gì?
Execution Context (Ngữ cảnh thực thi) của Lambda là một môi trường thực thi tạm thời mà AWS cung cấp khi Lambda được kích hoạt (invoked). Đây là môi trường mà Lambda sử dụng để khởi tạo các phụ thuộc bên ngoài (external dependencies) như kết nối cơ sở dữ liệu, khách hàng HTTP (HTTP clients), SDK của AWS, và các đối tượng kết nối khác.
Lợi ích của Lambda Execution Context
Lambda Execution Context có thể giúp bạn tiết kiệm thời gian trong việc khởi tạo lại các đối tượng và kết nối trong các lần gọi hàm sau đó (subsequent invocations). Đây là một kỹ thuật rất quan trọng để giảm thời gian thực thi hàm Lambda, đặc biệt đối với các ứng dụng cần kết nối đến cơ sở dữ liệu hoặc dịch vụ bên ngoài.
1. Tái sử dụng (Reuse) context giữa các lần gọi Lambda
Khi Lambda được kích hoạt lần đầu, nó sẽ khởi tạo môi trường thực thi và tất cả các đối tượng, kết nối cần thiết (ví dụ: kết nối tới RDS, DynamoDB, hoặc tạo đối tượng cho SDK của AWS).
AWS sẽ duy trì ngữ cảnh thực thi này trong một thời gian nhất định (khoảng vài phút) để có thể tái sử dụng nếu Lambda được gọi lại. Điều này giúp tiết kiệm thời gian cho lần gọi tiếp theo vì các kết nối đã được thiết lập sẵn, không cần khởi tạo lại từ đầu.
Ví dụ:
Lần gọi đầu tiên: Bạn có một hàm Lambda kết nối với RDS (cơ sở dữ liệu quan hệ của AWS). Khi hàm được gọi lần đầu, nó sẽ khởi tạo kết nối với RDS, điều này có thể mất vài mili giây đến vài giây, tùy thuộc vào độ phức tạp của kết nối.
Lần gọi tiếp theo: Nếu Lambda được gọi lại trong khoảng thời gian ngữ cảnh thực thi vẫn còn được giữ, nó có thể tái sử dụng kết nối đã có mà không cần phải tạo kết nối mới. Điều này giúp giảm đáng kể thời gian thực thi.
2. Khởi tạo các phụ thuộc một lần duy nhất
Một lợi ích lớn khác của Execution Context là bạn chỉ cần khởi tạo các đối tượng phụ thuộc một lần duy nhất trong suốt vòng đời của Lambda. Điều này đặc biệt hữu ích cho các ứng dụng cần kết nối tới cơ sở dữ liệu hoặc thực hiện các tác vụ yêu cầu nhiều tài nguyên.
Ví dụ:
- Giả sử bạn có một hàm Lambda gửi yêu cầu HTTP tới một API bên ngoài. Thay vì khởi tạo lại HTTP client cho mỗi lần gọi, bạn có thể khởi tạo HTTP client này trong ngữ cảnh thực thi và tái sử dụng nó cho tất cả các lần gọi sau.
/tmp Directory
Một phần của Execution Context bao gồm thư mục /tmp, đây là thư mục tạm thời duy nhất mà Lambda có thể sử dụng để lưu trữ dữ liệu trong quá trình thực thi. Bạn có thể lưu trữ tạm thời các tệp tin hoặc dữ liệu ở đây, nhưng cần lưu ý:
Dung lượng giới hạn: Bạn chỉ có thể lưu tối đa 512 MB dữ liệu trong thư mục này.
Không đảm bảo lưu trữ lâu dài: Dữ liệu trong thư mục
/tmp
sẽ bị xóa sau khi Lambda bị tắt, hoặc khi Lambda bị khởi tạo lại từ đầu (cold start).
Ví dụ về sử dụng /tmp
Giả sử bạn có một hàm Lambda nhận một tệp ảnh từ người dùng, xử lý ảnh đó, và tải nó lên S3.
Bước 1: Lambda nhận tệp ảnh và lưu tạm thời trong thư mục /tmp.
Bước 2: Lambda xử lý tệp ảnh (resize, thêm watermark, v.v.).
Bước 3: Lambda tải ảnh đã được xử lý lên S3.
Bước 4: Sau khi hoàn thành, tệp ảnh tạm thời trong
/tmp
sẽ tự động bị xóa khi Lambda kết thúc hoặc được AWS thu hồi ngữ cảnh thực thi.
Cold Start và Warm Start
Khi nói về Lambda Execution Context, cần hiểu rõ hai khái niệm:
Cold Start: Là khi Lambda được khởi tạo hoàn toàn mới, AWS cần phải tạo môi trường thực thi từ đầu, khởi tạo lại các phụ thuộc, kết nối, và tạo một ngữ cảnh thực thi hoàn toàn mới. Cold Start thường xảy ra khi Lambda chưa được gọi trong một thời gian dài hoặc khi AWS cần phân bổ thêm tài nguyên.
Warm Start: Là khi Lambda tái sử dụng ngữ cảnh thực thi cũ, giúp giảm thời gian khởi động vì các phụ thuộc đã được khởi tạo sẵn và sẵn sàng sử dụng.
Ví dụ về Cold Start và Warm Start
Cold Start: Lần đầu tiên hàm Lambda của bạn được gọi sau một khoảng thời gian dài không hoạt động. AWS sẽ tạo môi trường thực thi mới và khởi tạo tất cả các phụ thuộc.
Warm Start: Nếu Lambda được gọi liên tục, môi trường thực thi sẽ được tái sử dụng. Việc này giúp giảm thời gian thực thi vì Lambda không cần phải khởi tạo lại từ đầu.
Tối ưu hóa việc sử dụng Lambda Execution Context
Để tận dụng tối đa Lambda Execution Context và tối ưu hóa thời gian thực thi của hàm Lambda, bạn nên tuân theo các nguyên tắc sau:
Khởi tạo các kết nối bên ngoài (như cơ sở dữ liệu) ở bên ngoài handler Lambda:
- Điều này giúp kết nối được tái sử dụng trong các lần gọi hàm tiếp theo nếu ngữ cảnh thực thi vẫn còn tồn tại.
Ví dụ: Đặt mã kết nối tới RDS hoặc DynamoDB ở bên ngoài hàm chính (handler
) để nó chỉ được khởi tạo một lần trong suốt vòng đời của Lambda.
javascript
Copy code
// Khởi tạo kết nối bên ngoài hàm handler
const dbConnection = createDatabaseConnection();
exports.handler = async (event) => {
// Sử dụng kết nối đã khởi tạo
const result = await dbConnection.query('SELECT * FROM users');
return result;
};
Sử dụng thư mục
/tmp
để lưu trữ tạm thời:- Nếu bạn cần lưu trữ tạm thời dữ liệu trong quá trình thực thi, hãy sử dụng thư mục
/tmp
. Điều này rất hữu ích cho các tác vụ xử lý tệp tin hoặc cache dữ liệu.
- Nếu bạn cần lưu trữ tạm thời dữ liệu trong quá trình thực thi, hãy sử dụng thư mục
Kết luận
Lambda Execution Context là một yếu tố quan trọng giúp tối ưu hóa hiệu suất hàm Lambda, đặc biệt trong các tình huống cần kết nối cơ sở dữ liệu hoặc truy cập tài nguyên bên ngoài. Bằng cách tận dụng context này, bạn có thể giảm thời gian khởi tạo lại các phụ thuộc giữa các lần gọi Lambda, từ đó giúp ứng dụng chạy nhanh và hiệu quả hơn.
1. Tại sao nên khởi tạo đối tượng bên ngoài handler?
Trong AWS Lambda, mỗi lần hàm được gọi (invocation), AWS sẽ thực thi mã trong hàm handler của bạn. Nếu bạn khởi tạo các đối tượng kết nối (như kết nối tới cơ sở dữ liệu, khách hàng HTTP) bên trong handler, thì những đối tượng này sẽ được khởi tạo lại mỗi lần hàm được gọi. Điều này không chỉ làm tăng thời gian thực thi mà còn gây ra chi phí tài nguyên không cần thiết.
Ví dụ BAD (Khởi tạo đối tượng bên trong handler)
python
Copy code
import os
def get_user_handler(event, context):
DB_URL = os.getenv("DB_URL")
db_client = db.connect(DB_URL) # Kết nối cơ sở dữ liệu được tạo mỗi lần hàm được gọi
user = db_client.get(user_id = event["user_id"]) # Lấy dữ liệu người dùng
return user
Vấn đề ở đây:
Mỗi lần hàm Lambda được kích hoạt, kết nối tới cơ sở dữ liệu sẽ được thiết lập lại, điều này làm tăng đáng kể thời gian xử lý, đặc biệt khi có nhiều lần gọi hàm trong một khoảng thời gian ngắn.
Nếu cơ sở dữ liệu của bạn có giới hạn kết nối, điều này cũng có thể dẫn đến tình trạng quá tải kết nối và làm giảm hiệu suất của hệ thống.
Ví dụ GOOD (Khởi tạo đối tượng bên ngoài handler)
python
Copy code
import os
DB_URL = os.getenv("DB_URL")
db_client = db.connect(DB_URL) # Kết nối cơ sở dữ liệu được tạo một lần và tái sử dụng
def get_user_handler(event, context):
user = db_client.get(user_id = event["user_id"]) # Lấy dữ liệu người dùng
return user
Ưu điểm:
Kết nối tới cơ sở dữ liệu chỉ được tạo một lần và tái sử dụng trong các lần gọi hàm sau đó (nếu Lambda sử dụng ngữ cảnh thực thi cũ – warm start).
Điều này giúp giảm thời gian khởi tạo và cải thiện hiệu suất tổng thể của Lambda.
2. Cold Start vs Warm Start
Như đã giải thích ở phần trước về Execution Context, khi Lambda được khởi tạo từ đầu (cold start), AWS sẽ tạo một môi trường thực thi mới và mọi thứ sẽ khởi tạo lại. Tuy nhiên, trong trường hợp warm start, môi trường thực thi cũ vẫn còn, do đó các đối tượng khởi tạo bên ngoài hàm handler sẽ được tái sử dụng.
Cold Start: Khi Lambda khởi tạo lần đầu tiên hoặc sau một thời gian không hoạt động, kết nối sẽ được tạo lại từ đầu.
Warm Start: Các lần gọi sau, kết nối đã được thiết lập sẵn và có thể được tái sử dụng mà không cần khởi tạo lại.
Ví dụ về Cold Start và Warm Start
Giả sử bạn có một hàm Lambda gọi tới cơ sở dữ liệu RDS:
Lần đầu tiên gọi hàm Lambda:
- Lambda cần thiết lập kết nối tới RDS, điều này có thể mất một chút thời gian. Đây là cold start.
Lần gọi hàm tiếp theo:
- Lambda có thể tái sử dụng kết nối đã được thiết lập trong lần gọi trước (warm start), điều này giúp tiết kiệm thời gian và cải thiện hiệu suất.
3. Khi nào nên khởi tạo đối tượng bên ngoài handler?
Tình huống lý tưởng:
- Bất cứ khi nào bạn có các phụ thuộc bên ngoài (như kết nối cơ sở dữ liệu, HTTP client, AWS SDK client), bạn nên khởi tạo chúng bên ngoài hàm handler để tái sử dụng giữa các lần gọi hàm.
Tình huống cần lưu ý:
- Đối tượng không thể tái sử dụng: Nếu đối tượng hoặc kết nối không thể tái sử dụng an toàn giữa các lần gọi (ví dụ như nếu nó chứa thông tin trạng thái thay đổi liên tục), thì bạn có thể cần phải khởi tạo lại bên trong handler. Tuy nhiên, hầu hết các kết nối như database hoặc HTTP clients thường có thể tái sử dụng.
4. Tối ưu hóa kết nối cơ sở dữ liệu với Lambda
Khi bạn sử dụng Lambda để tương tác với cơ sở dữ liệu (RDS, DynamoDB, v.v.), điều quan trọng là phải tối ưu hóa kết nối để tránh tình trạng quá tải kết nối. Đây là một số lưu ý:
Sử dụng Connection Pooling (Tái sử dụng kết nối):
- Nếu cơ sở dữ liệu hỗ trợ connection pooling, hãy đảm bảo bạn sử dụng nó để giảm tải kết nối mới mỗi khi hàm Lambda được gọi.
Thiết lập timeout hợp lý cho kết nối:
- Đảm bảo rằng kết nối được thiết lập với thời gian timeout hợp lý để tránh các kết nối không cần thiết vẫn mở quá lâu mà không sử dụng.
Ví dụ về tái sử dụng kết nối RDS
python
Copy code
import os
import pymysql # Sử dụng thư viện pymysql để kết nối MySQL
DB_HOST = os.getenv("DB_HOST")
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_NAME = os.getenv("DB_NAME")
# Kết nối cơ sở dữ liệu được khởi tạo bên ngoài handler và tái sử dụng
connection = pymysql.connect(host=DB_HOST, user=DB_USER, password=DB_PASSWORD, database=DB_NAME)
def lambda_handler(event, context):
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM users WHERE id=%s", (event['user_id'],))
result = cursor.fetchone()
return result
Trong ví dụ này:
Kết nối tới MySQL được khởi tạo một lần duy nhất và có thể tái sử dụng trong các lần gọi Lambda tiếp theo.
Điều này giúp giảm đáng kể thời gian khởi tạo và cải thiện hiệu suất tổng thể của Lambda.
5. Kết luận
Việc khởi tạo đối tượng bên ngoài hàm handler là một trong những kỹ thuật tối ưu quan trọng khi làm việc với AWS Lambda. Điều này không chỉ giúp cải thiện hiệu suất bằng cách tái sử dụng kết nối mà còn giảm chi phí tài nguyên, đặc biệt khi làm việc với các dịch vụ yêu cầu kết nối lâu dài như cơ sở dữ liệu.
1. Thư mục /tmp
trong AWS Lambda là gì?
Thư mục /tmp
là một không gian lưu trữ tạm thời mà mỗi hàm Lambda có thể sử dụng để lưu trữ dữ liệu tạm thời trong quá trình thực thi.
Dung lượng tối đa: Bạn có thể sử dụng tối đa 10 GB dung lượng trong thư mục
/tmp
cho mỗi lần chạy Lambda.Mục đích sử dụng: Thư mục này rất hữu ích khi bạn cần lưu trữ tạm thời các tệp lớn hoặc dữ liệu khi thực thi các tác vụ như xử lý ảnh, video, hoặc tải xuống tệp từ một nguồn bên ngoài trước khi tiếp tục xử lý.
2. Khi nào nên sử dụng thư mục /tmp
?
Tình huống 1: Lambda cần tải tệp lớn từ S3 để xử lý
Giả sử bạn có một hàm Lambda thực hiện xử lý ảnh. Lambda cần tải một tệp ảnh lớn từ S3, xử lý nó (resize, thêm watermark), sau đó tải kết quả trở lại S3.
- Giải pháp: Bạn có thể sử dụng thư mục
/tmp
để lưu trữ tạm thời tệp ảnh khi đang thực hiện xử lý.
Ví dụ mã:
python
Copy code
import boto3
import os
s3 = boto3.client('s3')
def lambda_handler(event, context):
# Tải tệp từ S3 về thư mục /tmp
s3.download_file('my-bucket', 'large_image.jpg', '/tmp/large_image.jpg')
# Xử lý tệp (giả sử là thay đổi kích thước ảnh)
process_image('/tmp/large_image.jpg')
# Tải tệp đã xử lý ngược trở lại S3
s3.upload_file('/tmp/large_image.jpg', 'my-bucket', 'processed_image.jpg')
return "Processing complete!"
Trong ví dụ này:
Tệp ảnh lớn được tải về thư mục
/tmp
để xử lý mà không ảnh hưởng tới bộ nhớ RAM của Lambda.Sau khi xử lý xong, tệp được tải lên S3 và dữ liệu trong
/tmp
có thể bị xóa sau khi Lambda hoàn tất.
Tình huống 2: Lambda cần dung lượng lưu trữ lớn hơn RAM để xử lý dữ liệu
Nếu ứng dụng của bạn cần xử lý dữ liệu lớn, nhưng bộ nhớ RAM không đủ để chứa toàn bộ dữ liệu, bạn có thể sử dụng /tmp
để lưu trữ tạm thời dữ liệu.
Ví dụ: Bạn cần xử lý một tệp log lớn trước khi phân tích.
Ví dụ mã:
python
Copy code
def lambda_handler(event, context):
# Giả sử bạn nhận được tệp log lớn từ một API bên ngoài
log_data = download_log_file()
# Ghi dữ liệu log vào thư mục /tmp để xử lý
with open('/tmp/log_file.txt', 'w') as file:
file.write(log_data)
# Đọc lại và phân tích dữ liệu từ file trong /tmp
with open('/tmp/log_file.txt', 'r') as file:
process_log(file)
return "Log processing complete!"
Trong ví dụ này:
- Lambda có thể lưu trữ tạm thời dữ liệu trong
/tmp
để xử lý mà không cần lo lắng về việc giới hạn dung lượng bộ nhớ RAM.
3. Nội dung trong /tmp
có thể tồn tại qua các lần gọi hàm Lambda (Warm Start)
Nội dung trong thư mục /tmp
sẽ tồn tại trong suốt thời gian ngữ cảnh thực thi (execution context) của Lambda được giữ lại, điều này có thể giúp tạo ra cache tạm thời giữa các lần gọi hàm Lambda.
Ví dụ: Nếu hàm Lambda của bạn được gọi nhiều lần liên tiếp, và mỗi lần đều cần truy cập dữ liệu lớn từ một API, bạn có thể lưu dữ liệu vào /tmp
trong lần gọi đầu tiên và tái sử dụng nó trong các lần gọi sau để tiết kiệm thời gian tải xuống.
4. Khi nào nên sử dụng S3 thay vì /tmp
?
Nếu bạn cần lưu trữ lâu dài hoặc cần dữ liệu được truy cập thường xuyên từ nhiều nguồn, bạn nên sử dụng S3 thay vì thư mục /tmp
. Lý do là vì /tmp
chỉ mang tính chất tạm thời, và dữ liệu có thể bị mất nếu ngữ cảnh thực thi bị xóa hoặc Lambda bị khởi tạo lại.
Tình huống sử dụng S3
- Lưu trữ lâu dài: Nếu bạn cần lưu trữ tệp hoặc dữ liệu một cách lâu dài và muốn chia sẻ dữ liệu đó với nhiều dịch vụ khác hoặc các lần gọi Lambda khác nhau, S3 là lựa chọn tốt hơn.
Ví dụ: Bạn có một hàm Lambda ghi dữ liệu phân tích về tệp log lên S3 để lưu trữ và báo cáo.
5. Bảo mật cho dữ liệu trong thư mục /tmp
Nếu bạn lưu trữ dữ liệu nhạy cảm trong /tmp
, bạn cần mã hóa nó để đảm bảo an toàn. AWS Lambda cung cấp KMS (Key Management Service) để giúp bạn tạo các khóa mã hóa (Data Keys) để bảo vệ dữ liệu.
Mã hóa dữ liệu trong /tmp
Bạn có thể sử dụng AWS KMS để mã hóa dữ liệu trước khi lưu vào /tmp
.
Ví dụ mã hóa dữ liệu trong /tmp
với KMS:
python
Copy code
import boto3
from cryptography.fernet import Fernet
# Tạo khóa mã hóa bằng KMS
kms = boto3.client('kms')
response = kms.generate_data_key(KeyId='alias/my-kms-key', KeySpec='AES_256')
data_key = response['Plaintext']
encrypted_key = response['CiphertextBlob']
# Tạo đối tượng Fernet để mã hóa
cipher = Fernet(data_key)
def lambda_handler(event, context):
# Dữ liệu cần lưu trữ
data = "Sensitive information"
# Mã hóa dữ liệu
encrypted_data = cipher.encrypt(data.encode())
# Lưu dữ liệu mã hóa vào /tmp
with open('/tmp/encrypted_data.txt', 'wb') as file:
file.write(encrypted_data)
return "Data encrypted and saved in /tmp"
6. Kết luận
Thư mục /tmp
là một công cụ mạnh mẽ giúp bạn quản lý lưu trữ tạm thời cho các tác vụ xử lý tệp hoặc dữ liệu lớn trong AWS Lambda. Tuy nhiên, cần lưu ý rằng dung lượng có giới hạn và không nên sử dụng cho lưu trữ lâu dài. Nếu bạn cần lưu trữ dữ liệu lâu dài, S3 sẽ là giải pháp tốt hơn.
1. Lambda Layers là gì?
Lambda Layers là một tính năng trong AWS Lambda cho phép bạn tách riêng các phụ thuộc bên ngoài (như thư viện, SDK, framework) ra khỏi mã nguồn chính của hàm Lambda. Điều này giúp bạn có thể tái sử dụng các thư viện này giữa nhiều hàm Lambda khác nhau mà không cần phải tích hợp chúng vào mỗi hàm.
Lợi ích của việc sử dụng Lambda Layers:
Tái sử dụng: Bạn có thể tái sử dụng cùng một layer (thư viện hoặc runtime) cho nhiều hàm Lambda khác nhau, giúp giảm kích thước gói triển khai của hàm Lambda.
Quản lý dễ dàng: Thay vì phải nhúng tất cả các thư viện vào từng hàm Lambda, bạn có thể tách chúng ra thành các layers, giúp gói triển khai của bạn nhẹ hơn và dễ bảo trì hơn.
Custom Runtimes: Bạn cũng có thể sử dụng Lambda Layers để triển khai các runtime tùy chỉnh, ví dụ như C++ hoặc Rust (như đã đề cập trong ảnh).
2. Ví dụ về Lambda Layers từ ảnh
Ảnh minh họa cách bạn có thể tối ưu hóa ứng dụng Lambda bằng cách tách riêng các thư viện nặng (heavy libraries) ra khỏi hàm chính.
Trường hợp không sử dụng Lambda Layers (bên trái):
Application Package 1 (30.02MB):
Hàm lambda_function_1.py có kèm theo các thư viện lớn:
my_heavy_library_1.
my_heavy_library_2.
Kích thước tổng cộng của gói triển khai là 30.02 MB.
Trường hợp sử dụng Lambda Layers (bên phải):
Application Package 1 (20KB):
Hàm lambda_function_1.py chỉ còn mã nguồn chính, không chứa các thư viện nặng.
Các thư viện lớn đã được tách ra và đưa vào các Lambda Layers:
Lambda Layer 1 (10MB): chứa my_heavy_library_1.
Lambda Layer 2 (30MB): chứa my_heavy_library_2.
Kích thước của hàm Lambda chỉ còn 20KB.
Các layers này có thể được tái sử dụng cho nhiều hàm Lambda khác nhau.
Ví dụ, lambda_function_2.py (60KB) có thể sử dụng lại các Lambda Layers tương tự, giúp giảm thiểu việc sao chép các thư viện này nhiều lần trong các hàm khác nhau.
3. Cách sử dụng Lambda Layers
Bước 1: Tạo Lambda Layer
Bạn có thể tạo một Lambda Layer để chứa các thư viện mà hàm Lambda của bạn cần sử dụng. Ví dụ, nếu bạn sử dụng thư viện Python như requests
, bạn có thể đóng gói thư viện này vào một layer riêng biệt.
Ví dụ: Tạo Layer chứa thư viện requests
Cài đặt thư viện
requests
trong một thư mục riêng:bash Copy code mkdir python pip install requests -t python/
Đóng gói thư mục
python
thành tệp.zip
:bash Copy code zip -r layer.zip python/
Tạo Lambda Layer trên AWS:
Truy cập AWS Lambda Console.
Chọn Layers và tạo một layer mới, tải lên tệp layer.zip.
Bước 2: Thêm Layer vào hàm Lambda
Sau khi tạo xong Layer, bạn có thể thêm nó vào hàm Lambda của mình. Khi triển khai hàm Lambda, bạn chỉ cần thêm layer này mà không cần phải tải lại thư viện requests
.
- Khi tạo hoặc cập nhật hàm Lambda, bạn sẽ thấy tùy chọn để thêm Layer. Chọn layer mà bạn vừa tạo và lưu lại cấu hình.
Bước 3: Sử dụng Layer trong hàm Lambda
Sau khi thêm Layer, bạn có thể sử dụng thư viện requests
trong mã của hàm Lambda như bình thường.
Ví dụ mã Lambda sử dụng thư viện requests
từ Layer:
python
Copy code
import requests
def lambda_handler(event, context):
response = requests.get('<https://jsonplaceholder.typicode.com/todos/1>')
return response.json()
Nhờ việc tách riêng thư viện requests
ra khỏi gói triển khai chính, kích thước của hàm Lambda sẽ nhỏ hơn, giúp triển khai nhanh chóng và hiệu quả hơn.
4. Custom Runtimes với Lambda Layers
Ngoài việc sử dụng các thư viện, bạn cũng có thể triển khai runtime tùy chỉnh với Lambda Layers. AWS Lambda hỗ trợ các ngôn ngữ như Python, Node.js, Go, Java, nhưng nếu bạn muốn sử dụng ngôn ngữ khác như C++ hoặc Rust, bạn có thể tạo custom runtime thông qua Lambda Layers.
Ví dụ:
C++ Runtime: Bạn có thể tạo runtime C++ và triển khai nó thông qua Lambda Layer. AWS đã cung cấp một dự án mẫu trên GitHub để bạn có thể tham khảo aws-lambda-cpp.
Rust Runtime: Tương tự, nếu bạn muốn sử dụng ngôn ngữ Rust cho Lambda, bạn có thể tham khảo dự án aws-lambda-rust-runtime.
5. Tối ưu hóa việc sử dụng Lambda Layers
Tái sử dụng thư viện: Nếu bạn có nhiều hàm Lambda sử dụng cùng một thư viện, bạn nên sử dụng Lambda Layers để tái sử dụng chúng, thay vì nhúng thư viện vào từng hàm.
Giảm kích thước gói triển khai: Tách các thư viện lớn ra khỏi gói triển khai chính của hàm Lambda sẽ giúp giảm kích thước của hàm, từ đó giúp triển khai nhanh hơn và giảm chi phí lưu trữ.
Sử dụng Custom Runtimes: Đối với các ứng dụng phức tạp yêu cầu ngôn ngữ hoặc môi trường tùy chỉnh, Lambda Layers là một công cụ lý tưởng để triển khai runtime tùy chỉnh.
6. Kết luận
Lambda Layers là một công cụ mạnh mẽ giúp tối ưu hóa các hàm Lambda bằng cách tách riêng các phụ thuộc ra khỏi mã chính, giúp bạn quản lý tốt hơn các thư viện lớn và tái sử dụng chúng giữa các hàm Lambda khác nhau. Hiểu và sử dụng đúng cách Lambda Layers sẽ giúp bạn xây dựng ứng dụng hiệu quả hơn, đồng thời cũng là một phần quan trọng để vượt qua kỳ thi AWS Certified Developer – Associate.
1. EFS là gì và tại sao lại cần thiết cho Lambda?
Amazon EFS (Elastic File System) là một dịch vụ lưu trữ tệp được AWS cung cấp, với tính năng chính là:
Tự động mở rộng (scalable): Dung lượng của EFS có thể tự động mở rộng hoặc thu hẹp theo lượng dữ liệu bạn lưu trữ.
Chia sẻ dữ liệu: EFS có thể được truy cập đồng thời bởi nhiều instance EC2, Lambda functions, và các dịch vụ khác của AWS.
Việc kết nối EFS với Lambda đặc biệt hữu ích khi bạn cần xử lý các tác vụ mà dữ liệu lớn hoặc chia sẻ dữ liệu giữa các hàm Lambda là cần thiết.
2. Cách kết nối EFS vào Lambda (Mount EFS)
Điều kiện bắt buộc: Lambda của bạn phải được triển khai trong VPC (Virtual Private Cloud) để có thể kết nối với EFS.
Bước 1: Cấu hình VPC cho Lambda
Đảm bảo hàm Lambda của bạn được cấu hình để chạy trong VPC, với các subnet và security group phù hợp để truy cập hệ thống EFS.
Chọn subnet và nhóm bảo mật (security group) phù hợp khi cấu hình hàm Lambda, đảm bảo rằng các subnet này có thể truy cập đến EFS.
Bước 2: Mount EFS vào Lambda
Bạn cần cấu hình Lambda để mount EFS vào một thư mục cục bộ (local directory) trong quá trình khởi tạo (initialization).
Sử dụng EFS Access Points để cung cấp quyền truy cập cho Lambda tới các thư mục cụ thể trên hệ thống tệp EFS.
Ví dụ minh họa từ hình:
Trong hình minh họa, hàm Lambda đang chạy trong VPC với hai subnet riêng biệt (Private Subnet A và Private Subnet B) thuộc hai Availability Zones khác nhau (A và B).
Các hàm Lambda này sử dụng EFS Access Point để kết nối đến hệ thống tệp EFS và truy cập dữ liệu thông qua thư mục được mount.
3. Cấu hình EFS Access Points
EFS Access Points là một cách an toàn và hiệu quả để cung cấp quyền truy cập đến các phần cụ thể của hệ thống tệp EFS. Mỗi hàm Lambda sẽ sử dụng một Access Point để kết nối đến thư mục hoặc file trên EFS.
Ví dụ cấu hình Access Point cho Lambda:
Tạo Access Point trong EFS Console:
- Đầu tiên, bạn cần truy cập vào Amazon EFS Console và tạo một Access Point để chỉ định đường dẫn (path) mà Lambda có thể truy cập.
Cấu hình Lambda sử dụng Access Point:
- Trong phần cấu hình của hàm Lambda, khi bạn thêm EFS File System, bạn sẽ được yêu cầu chỉ định Access Point để kết nối.
4. Giới hạn và những điều cần lưu ý khi sử dụng EFS với Lambda
4.1 Giới hạn kết nối của EFS
Mỗi instance Lambda được khởi tạo sẽ tương đương với một kết nối đến EFS. Nếu bạn khởi chạy nhiều hàm Lambda đồng thời, điều này sẽ tạo ra nhiều kết nối đến EFS.
Hãy chú ý đến giới hạn kết nối của EFS, đặc biệt khi triển khai Lambda ở quy mô lớn với hàng ngàn kết nối cùng lúc. Điều này có thể dẫn đến giới hạn bùng nổ kết nối (connection burst limits), làm giảm hiệu suất hoặc gây ra lỗi.
4.2 Tốc độ đọc/ghi dữ liệu
Hiệu suất của Lambda khi đọc/ghi dữ liệu từ EFS sẽ phụ thuộc vào lưu lượng truy cập và tốc độ của EFS.
Đối với các tác vụ yêu cầu truy cập dữ liệu lớn và thường xuyên, bạn cần đảm bảo rằng EFS của bạn được cấu hình để mở rộng hiệu suất một cách tự động (nếu cần thiết).
5. Ví dụ thực tế sử dụng EFS với Lambda
Tình huống 1: Lambda xử lý video lớn
Giả sử bạn có một hàm Lambda thực hiện việc xử lý video. Các video có kích thước lớn, và bạn cần lưu trữ tạm thời các tệp video để xử lý (ví dụ: nén hoặc thay đổi định dạng).
- Giải pháp: Bạn có thể sử dụng EFS để lưu trữ tạm thời các video lớn và hàm Lambda có thể xử lý chúng mà không lo lắng về giới hạn dung lượng của thư mục
/tmp
.
Cách triển khai:
Lưu trữ tệp video lớn trong EFS thông qua Access Point.
Lambda kết nối đến EFS, tải video vào bộ nhớ tạm thời và thực hiện xử lý.
Sau khi xử lý xong, lưu kết quả video đã chỉnh sửa trở lại EFS hoặc S3.
Tình huống 2: Chia sẻ dữ liệu giữa các hàm Lambda
Giả sử bạn có nhiều hàm Lambda thực hiện các tác vụ khác nhau nhưng cần truy cập chung một bộ dữ liệu (ví dụ: một tập tin cấu hình lớn hoặc một tập tin cơ sở dữ liệu SQLite).
- Giải pháp: Sử dụng EFS để lưu trữ tập tin chung và các hàm Lambda có thể truy cập thông qua EFS Access Points.
Cách triển khai:
Lưu trữ tập tin cấu hình hoặc cơ sở dữ liệu trên EFS.
Mỗi hàm Lambda sẽ mount EFS thông qua Access Point để đọc và ghi dữ liệu vào tệp này.
6. Kết luận
Kết nối Amazon EFS với AWS Lambda mang lại nhiều lợi ích trong các trường hợp cần lưu trữ hoặc xử lý dữ liệu lớn và chia sẻ dữ liệu giữa các hàm Lambda. Tuy nhiên, bạn cần chú ý đến các giới hạn kết nối và hiệu suất của EFS khi sử dụng ở quy mô lớn.
EFS Access Points cung cấp một cách an toàn và tiện lợi để quản lý quyền truy cập giữa các hàm Lambda và EFS, giúp bạn có thể dễ dàng chia sẻ dữ liệu hoặc lưu trữ tạm thời các tệp lớn.
các tùy chọn lưu trữ khi làm việc với AWS Lambda, bao gồm 4 tùy chọn chính: Ephemeral Storage (/tmp
), Lambda Layers, Amazon S3, và Amazon EFS. Việc hiểu rõ các tùy chọn lưu trữ này sẽ giúp bạn chọn lựa phương án phù hợp nhất cho từng trường hợp sử dụng, đặc biệt khi chuẩn bị cho kỳ thi AWS Certified Developer – Associate.
Dưới đây là giải thích chi tiết, rõ ràng về các tùy chọn lưu trữ trong AWS Lambda, kèm theo các ví dụ cụ thể.
1. Ephemeral Storage (/tmp
)
Giới thiệu:
- Ephemeral Storage (lưu trữ tạm thời) được AWS cung cấp cho Lambda thông qua thư mục
/tmp
. Đây là không gian lưu trữ tạm thời và có thể bị xóa sau khi hàm Lambda hoàn tất hoặc khi môi trường thực thi của Lambda bị khởi tạo lại (cold start).
Các đặc điểm chính:
Max. Size (Dung lượng tối đa): 10,240 MB (tức 10GB).
Persistence (Tính bền vững): Ephemeral – dữ liệu không được lưu trữ lâu dài, có thể mất khi môi trường Lambda bị khởi tạo lại.
Content: Dữ liệu động, có thể thay đổi liên tục giữa các lần gọi Lambda.
Storage Type: Dạng hệ thống tệp (File System).
Operations Supported: Hỗ trợ mọi thao tác trên hệ thống tệp.
Pricing: Đã bao gồm trong chi phí của Lambda.
Sharing/Permissions: Chỉ dành cho phiên làm việc hiện tại của Lambda (Function Only).
Relative Data Access Speed: Nhanh nhất, vì lưu trữ ngay trên hệ thống của Lambda.
Shared Across All Invocations: Không – không thể chia sẻ giữa các lần gọi Lambda khác nhau.
Ví dụ:
- Xử lý tệp lớn: Bạn có một hàm Lambda tải xuống tệp từ S3 để xử lý (ví dụ, resize ảnh). Tệp này được lưu tạm thời trong
/tmp
để xử lý và sau đó được tải lên S3 sau khi hoàn tất.
python
Copy code
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
# Tải tệp về /tmp
s3.download_file('my-bucket', 'large_file.jpg', '/tmp/large_file.jpg')
# Xử lý tệp (ví dụ: resize ảnh)
# ...
# Tải tệp đã xử lý ngược lại S3
s3.upload_file('/tmp/large_file.jpg', 'my-bucket', 'processed_file.jpg')
return "Done!"
2. Lambda Layers
Giới thiệu:
- Lambda Layers là một cách để tách các thư viện và phụ thuộc (dependencies) ra khỏi mã nguồn chính của Lambda. Điều này giúp bạn có thể tái sử dụng các thư viện giữa nhiều hàm Lambda khác nhau mà không cần nhúng các thư viện này vào từng hàm.
Các đặc điểm chính:
Max. Size: Mỗi hàm Lambda có thể sử dụng 5 layers, tổng cộng tối đa 250MB.
Persistence: Durable – các layers được lưu trữ và có thể tái sử dụng.
Content: Dữ liệu tĩnh (Static) – các layers thường chứa thư viện hoặc runtime không thay đổi thường xuyên.
Storage Type: Dạng tệp lưu trữ (Archive).
Operations Supported: Không thể thay đổi (Immutable).
Pricing: Đã bao gồm trong chi phí của Lambda.
Sharing/Permissions: Sử dụng IAM để kiểm soát quyền truy cập.
Relative Data Access Speed: Nhanh nhất, vì dữ liệu đã được load sẵn trong quá trình thực thi.
Shared Across All Invocations: Có – các layers có thể tái sử dụng giữa các hàm và lần gọi Lambda khác nhau.
Ví dụ:
- Sử dụng thư viện
requests
trong nhiều hàm Lambda: Thay vì nhúng thư viện này vào mỗi hàm, bạn có thể tạo một Layer chứa thư việnrequests
và thêm Layer này vào các hàm Lambda cần sử dụng.
python
Copy code
import requests
def lambda_handler(event, context):
response = requests.get('<https://jsonplaceholder.typicode.com/todos/1>')
return response.json()
3. Amazon S3
Giới thiệu:
- Amazon S3 là dịch vụ lưu trữ đối tượng (object storage) của AWS, rất phổ biến và phù hợp cho các tác vụ cần lưu trữ dữ liệu lâu dài và linh hoạt.
Các đặc điểm chính:
Max. Size: Không giới hạn, S3 có khả năng mở rộng linh hoạt (Elastic).
Persistence: Durable – dữ liệu trên S3 được lưu trữ bền vững với độ bền lên đến 99.999999999%.
Content: Dữ liệu động (Dynamic) – bạn có thể thêm, sửa đổi, và xóa dữ liệu.
Storage Type: Dạng đối tượng (Object Storage).
Operations Supported: Các thao tác với phiên bản (atomic với versioning).
Pricing: Tính phí theo lưu trữ, số lần yêu cầu, và băng thông dữ liệu.
Sharing/Permissions: Kiểm soát truy cập thông qua IAM.
Relative Data Access Speed: Nhanh, nhưng không nhanh bằng lưu trữ nội bộ như
/tmp
hoặc Layers.Shared Across All Invocations: Có – dữ liệu trên S3 có thể được chia sẻ giữa nhiều lần gọi Lambda khác nhau và giữa nhiều dịch vụ khác.
Ví dụ:
- Lưu trữ lâu dài cho tệp đã xử lý: Sau khi Lambda xử lý xong tệp, bạn có thể lưu trữ kết quả trên S3 để truy xuất sau này hoặc chia sẻ với các dịch vụ khác.
python
Copy code
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
# Tải lên tệp đã xử lý lên S3
s3.upload_file('/tmp/processed_file.jpg', 'my-bucket', 'processed_file.jpg')
return "Upload complete!"
4. Amazon EFS (Elastic File System)
Giới thiệu:
- Amazon EFS là dịch vụ lưu trữ tệp linh hoạt, có khả năng chia sẻ dữ liệu giữa nhiều hàm Lambda hoặc các instance EC2. EFS thích hợp cho các ứng dụng cần lưu trữ tệp lớn hoặc dữ liệu cần truy cập đồng thời từ nhiều nguồn.
Các đặc điểm chính:
Max. Size: Linh hoạt (Elastic), tự động mở rộng theo dung lượng dữ liệu lưu trữ.
Persistence: Durable – dữ liệu trên EFS được lưu trữ lâu dài.
Content: Dữ liệu động (Dynamic) – có thể thay đổi liên tục.
Storage Type: Hệ thống tệp (File System).
Operations Supported: Hỗ trợ mọi thao tác trên hệ thống tệp.
Pricing: Tính phí theo dung lượng lưu trữ, băng thông truyền tải, và throughput.
Sharing/Permissions: Kiểm soát truy cập thông qua IAM và NFS (Network File System).
Relative Data Access Speed: Rất nhanh, phù hợp cho các ứng dụng cần truy cập dữ liệu lớn.
Shared Across All Invocations: Có – dữ liệu trên EFS có thể được chia sẻ giữa nhiều lần gọi Lambda và nhiều dịch vụ khác.
Ví dụ:
- Chia sẻ dữ liệu giữa các hàm Lambda: Nếu bạn có nhiều hàm Lambda cần truy cập chung một cơ sở dữ liệu SQLite hoặc tệp cấu hình lớn, bạn có thể lưu trữ dữ liệu này trên EFS và các hàm Lambda sẽ truy cập nó qua các EFS Access Points.
python
Copy code
import os
def lambda_handler(event, context):
# Đọc dữ liệu từ file trên EFS
with open('/mnt/efs/data.txt', 'r') as file:
data = file.read()
return data
Kết luận
Mỗi tùy chọn lưu trữ trong AWS Lambda có các ưu điểm và nhược điểm riêng, và việc lựa chọn phụ thuộc vào yêu cầu của ứng dụng và tính chất dữ liệu:
Ephemeral Storage (
/tmp
): Lý tưởng cho lưu trữ tạm thời và xử lý dữ liệu lớn trong ngắn hạn.Lambda Layers: Dùng để tái sử dụng các thư viện và runtime giữa nhiều hàm Lambda.
Amazon S3: Thích hợp cho lưu trữ đối tượng bền vững, linh hoạt và có thể truy cập từ nhiều nguồn.
Amazon EFS: Dùng khi cần lưu trữ tệp lớn hoặc chia sẻ dữ liệu
Concurrency và Throttling trong AWS Lambda, một chủ đề quan trọng trong việc quản lý các hàm Lambda khi chạy đồng thời nhiều phiên bản (invocations) của hàm. Việc hiểu rõ cách Lambda quản lý concurrency (tính đồng thời) và throttling (giới hạn) là rất quan trọng để tối ưu hóa ứng dụng của bạn trên AWS và chuẩn bị cho kỳ thi AWS Certified Developer – Associate.
Dưới đây là giải thích chi tiết về các khái niệm liên quan đến Concurrency và Throttling trong AWS Lambda kèm theo các ví dụ minh họa để giúp bạn hiểu rõ hơn.
1. Concurrency (Tính đồng thời) trong AWS Lambda là gì?
Concurrency trong AWS Lambda là khả năng chạy đồng thời nhiều phiên bản của cùng một hàm Lambda. Điều này có nghĩa là nhiều lời gọi hàm (invocations) có thể xảy ra cùng lúc mà không cần đợi lời gọi trước hoàn thành.
Concurrency limit (Giới hạn tính đồng thời)
Giới hạn mặc định cho mỗi tài khoản AWS là 1000 phiên bản Lambda chạy đồng thời.
- Ví dụ: Nếu bạn có một hàm Lambda và nó được kích hoạt nhiều lần, AWS có thể chạy tối đa 1000 phiên bản của hàm đó cùng lúc.
Reserved Concurrency (Tính đồng thời được đặt trước)
- Bạn có thể thiết lập giới hạn tính đồng thời ở mức độ hàm Lambda bằng cách đặt trước tính đồng thời (Reserved Concurrency). Điều này giúp bạn giới hạn số lượng phiên bản của hàm Lambda có thể chạy đồng thời.
Ví dụ: Bạn đặt reserved concurrency = 5 cho một hàm Lambda. Điều này có nghĩa là chỉ có tối đa 5 phiên bản của hàm có thể chạy đồng thời tại một thời điểm. Nếu có nhiều hơn 5 lời gọi đến hàm, các lời gọi dư sẽ bị giới hạn (throttle).
2. Throttling (Giới hạn) là gì và cách nó hoạt động?
Throttling xảy ra khi số lượng phiên bản của hàm Lambda đang chạy vượt quá giới hạn tính đồng thời (concurrency limit). Khi điều này xảy ra, AWS sẽ không cho phép chạy thêm bất kỳ phiên bản nào mới và thay vào đó sẽ kích hoạt cơ chế throttle.
Throttle Behavior (Hành vi khi bị giới hạn)
Synchronous invocations (Lời gọi đồng bộ):
Nếu lời gọi Lambda là đồng bộ, khi vượt quá giới hạn tính đồng thời, nó sẽ trả về lỗi ThrottleError (HTTP 429).
Ví dụ: Khi API Gateway gọi Lambda và vượt quá giới hạn, nó sẽ nhận lỗi 429 - ThrottleError.
Asynchronous invocations (Lời gọi không đồng bộ):
Nếu lời gọi Lambda là không đồng bộ, khi bị throttle, nó sẽ tự động thử lại (retry) theo mặc định của AWS.
Nếu sau nhiều lần thử mà vẫn thất bại, lời gọi sẽ được gửi đến DLQ (Dead Letter Queue) nếu được cấu hình.
3. Ví dụ về Throttle Behavior
Trường hợp đồng bộ (Synchronous Invocation)
Giả sử bạn có một hàm Lambda được kích hoạt bởi API Gateway, và hàm này có giới hạn tính đồng thời là 10. Nếu cùng lúc có 15 yêu cầu đến API Gateway:
10 yêu cầu đầu tiên sẽ được xử lý bởi 10 phiên bản Lambda đang chạy.
5 yêu cầu còn lại sẽ gặp lỗi ThrottleError 429 vì số lượng phiên bản Lambda đã đạt giới hạn.
Trường hợp không đồng bộ (Asynchronous Invocation)
Giả sử bạn có một hàm Lambda được kích hoạt bởi SQS (Amazon Simple Queue Service), và hàm này có giới hạn tính đồng thời là 20. Nếu SQS gửi cùng lúc 25 tin nhắn để kích hoạt Lambda:
20 tin nhắn đầu tiên sẽ được xử lý bởi 20 phiên bản Lambda.
5 tin nhắn còn lại sẽ bị giới hạn và Lambda sẽ tự động thử lại.
Nếu sau nhiều lần thử mà vẫn thất bại, các tin nhắn này sẽ được gửi đến DLQ nếu được cấu hình.
4. Các cách tăng Concurrency Limit
Nếu ứng dụng của bạn cần xử lý nhiều lời gọi đồng thời hơn giới hạn mặc định 1000:
Mở ticket hỗ trợ với AWS để yêu cầu tăng giới hạn tính đồng thời.
AWS có thể xem xét và tăng giới hạn tùy thuộc vào yêu cầu và cấu hình ứng dụng của bạn.
5. Reserved Concurrency và Unreserved Concurrency
Reserved Concurrency (Tính đồng thời được đặt trước): Đây là giới hạn tối đa mà một hàm Lambda có thể chạy đồng thời. Nếu bạn đặt giá trị này cho một hàm, nó sẽ chỉ sử dụng đúng số lượng tính đồng thời mà bạn đã chỉ định.
- Ví dụ: Bạn có một hàm Lambda A và bạn đặt reserved concurrency = 10, điều này có nghĩa là hàm Lambda A sẽ chỉ có thể chạy tối đa 10 phiên bản cùng lúc.
Unreserved Concurrency (Tính đồng thời không được đặt trước): Đây là phần tính đồng thời còn lại cho các hàm Lambda khác trong tài khoản của bạn nếu bạn đặt reserved concurrency cho một số hàm cụ thể.
- Ví dụ: Nếu bạn có giới hạn toàn tài khoản là 1000, và bạn đã đặt trước 10 cho hàm Lambda A, thì phần còn lại sẽ là 990 dành cho tất cả các hàm Lambda khác trong tài khoản của bạn.
6. Ví dụ cụ thể về quản lý concurrency và throttling
Tình huống 1: Giới hạn tính đồng thời cho hàm Lambda xử lý dữ liệu
Giả sử bạn có một hàm Lambda xử lý dữ liệu từ một hệ thống, và hệ thống này không thể xử lý quá 5 yêu cầu cùng lúc. Bạn có thể cấu hình Reserved Concurrency cho hàm Lambda để giới hạn số phiên bản Lambda chạy đồng thời ở mức 5, giúp đảm bảo rằng hệ thống của bạn không bị quá tải.
Tình huống 2: Xử lý lỗi throttling trong API Gateway
Bạn có một hàm Lambda được kích hoạt bởi API Gateway, và bạn nhận thấy rằng khi có quá nhiều yêu cầu đến cùng lúc, một số yêu cầu trả về lỗi 429 - ThrottleError. Để giải quyết, bạn có thể:
Tăng giới hạn tính đồng thời bằng cách mở ticket với AWS.
Hoặc, bạn có thể cấu hình API Gateway để giảm tốc độ gửi yêu cầu đến Lambda, giúp tránh bị giới hạn tính đồng thời.
Kết luận
Hiểu rõ về Concurrency và Throttling trong AWS Lambda giúp bạn kiểm soát tốt hơn việc xử lý các lời gọi hàm đồng thời, tránh việc hệ thống bị quá tải, đồng thời tối ưu hóa tài nguyên và đảm bảo hiệu suất của ứng dụng.
1. Vấn đề về tính đồng thời (Lambda Concurrency Issue)
AWS Lambda cho phép chạy nhiều phiên bản của hàm Lambda cùng lúc (tính đồng thời). Tuy nhiên, nếu bạn không quản lý tốt tính đồng thời hoặc không đặt giới hạn hợp lý, bạn có thể gặp phải tình trạng throttling (giới hạn số lượng phiên bản đồng thời).
Concurrency limit (Giới hạn tính đồng thời)
Mặc định, tài khoản AWS của bạn có thể chạy tối đa 1000 phiên bản Lambda đồng thời trên toàn bộ các hàm Lambda.
Nếu không đặt reserved concurrency (tính đồng thời được đặt trước) cho từng hàm, tất cả các hàm Lambda của bạn sẽ chia sẻ chung giới hạn này.
Sự cố khi không đặt Reserved Concurrency
Nếu một hàm Lambda bị quá tải, nó có thể chiếm toàn bộ số lượng phiên bản tính đồng thời, dẫn đến tình trạng các hàm khác bị giới hạn và không thể chạy thêm.
Ví dụ từ hình minh họa:
Application Load Balancer: Nhiều người dùng cùng lúc gửi yêu cầu qua Application Load Balancer đến một hàm Lambda, tạo ra 1000 phiên bản Lambda chạy đồng thời.
Điều này có thể khiến các yêu cầu từ các dịch vụ khác như API Gateway và SDK/CLI bị giới hạn (throttled), gây ra lỗi khi các yêu cầu này không thể được thực hiện do hàm Lambda không còn slot để chạy thêm phiên bản mới.
2. Reserved Concurrency (Tính đồng thời được đặt trước)
Reserved Concurrency là tính năng cho phép bạn đặt trước một số lượng phiên bản Lambda có thể chạy đồng thời cho một hàm cụ thể. Khi bạn đặt reserved concurrency, bạn đảm bảo rằng hàm Lambda này sẽ chỉ sử dụng tối đa số lượng phiên bản mà bạn đã chỉ định, và các hàm khác sẽ không bị ảnh hưởng bởi việc sử dụng quá mức của hàm này.
Lợi ích của Reserved Concurrency:
Bảo vệ các hàm quan trọng: Bằng cách đặt giới hạn cho mỗi hàm Lambda, bạn có thể đảm bảo rằng một hàm không thể chiếm hết tất cả tài nguyên tính đồng thời, từ đó bảo vệ các hàm Lambda khác hoạt động ổn định.
Quản lý tốt hơn lưu lượng truy cập: Nếu bạn biết rằng một hàm Lambda có khả năng nhận nhiều yêu cầu đồng thời, bạn có thể dự phòng số lượng phiên bản cho các hàm khác để tránh bị gián đoạn.
Ví dụ:
- Giả sử bạn có một hàm Lambda phục vụ thông qua Application Load Balancer và hàm này có thể nhận lượng lớn yêu cầu từ nhiều người dùng cùng lúc. Để bảo vệ các hàm Lambda khác khỏi bị giới hạn, bạn có thể đặt reserved concurrency = 500 cho hàm này. Điều này đảm bảo hàm này chỉ có thể chạy tối đa 500 phiên bản cùng lúc, và còn lại 500 phiên bản cho các hàm khác trong tài khoản AWS của bạn.
3. Throttling (Giới hạn)
Throttling xảy ra khi số lượng lời gọi Lambda vượt quá giới hạn tính đồng thời. Khi điều này xảy ra, AWS sẽ từ chối các yêu cầu mới hoặc thử lại trong trường hợp lời gọi không đồng bộ.
Cách Throttling hoạt động:
Nếu Lambda bị giới hạn (throttled):
Đối với lời gọi đồng bộ (Synchronous Invocation): Lời gọi sẽ trả về lỗi ThrottleError (HTTP 429).
Đối với lời gọi không đồng bộ (Asynchronous Invocation): Lời gọi sẽ được tự động thử lại (retry) theo mặc định. Nếu lời gọi vẫn thất bại, nó sẽ được gửi đến DLQ (Dead Letter Queue) nếu được cấu hình.
Ví dụ về Throttling:
- API Gateway: Khi một hàm Lambda được kích hoạt bởi API Gateway và số lượng yêu cầu vượt quá giới hạn tính đồng thời, Lambda sẽ trả về lỗi 429 - ThrottleError cho các yêu cầu vượt quá. Điều này có thể gây ra sự cố với trải nghiệm người dùng nếu không được xử lý tốt.
4. Ví dụ về sự cố Concurrency
Tình huống 1: Sự cố do không đặt Reserved Concurrency
Giả sử bạn có một dịch vụ web được chạy bởi Application Load Balancer, và hàm Lambda xử lý yêu cầu từ ALB đang nhận một lượng lớn lưu lượng từ nhiều người dùng cùng lúc. Nếu không có giới hạn, hàm Lambda này có thể chiếm toàn bộ 1000 phiên bản đồng thời, dẫn đến các dịch vụ khác như API Gateway hoặc các ứng dụng sử dụng AWS SDK không thể gọi Lambda vì bị giới hạn.
- Giải pháp: Đặt reserved concurrency cho hàm Lambda của bạn, chẳng hạn như đặt giới hạn 600 phiên bản cho hàm xử lý yêu cầu từ ALB. Điều này đảm bảo rằng bạn còn lại 400 phiên bản cho các dịch vụ khác như API Gateway.
Tình huống 2: Throttling trong API Gateway
Giả sử bạn có một hàm Lambda phục vụ qua API Gateway, và hàm này bị giới hạn tính đồng thời là 50 phiên bản. Khi có quá nhiều yêu cầu đồng thời đến, API Gateway sẽ nhận được lỗi 429 - ThrottleError từ Lambda.
- Giải pháp: Bạn có thể mở rộng giới hạn tính đồng thời của Lambda hoặc sử dụng API Gateway Throttling để kiểm soát tốc độ gửi yêu cầu đến Lambda, giúp giảm thiểu tình trạng quá tải.
5. Kết luận
Hiểu và quản lý tính đồng thời (concurrency) trong AWS Lambda là yếu tố rất quan trọng để đảm bảo rằng ứng dụng của bạn hoạt động ổn định, đặc biệt khi có nhiều dịch vụ khác nhau cùng sử dụng Lambda. Đặt Reserved Concurrency cho các hàm Lambda là cách tốt nhất để kiểm soát lưu lượng và tránh việc một hàm chiếm quá nhiều tài nguyên, dẫn đến tình trạng throttling cho các hàm khác.
Concurrency và Asynchronous Invocations trong AWS Lambda, một khái niệm rất quan trọng để hiểu cách Lambda xử lý các lời gọi không đồng bộ và các vấn đề liên quan đến tính đồng thời. Việc này rất hữu ích khi chuẩn bị cho kỳ thi AWS Certified Developer – Associate.
Hãy cùng mình phân tích chi tiết và dễ hiểu nội dung này nhé.
1. Asynchronous Invocations (Lời gọi không đồng bộ)
AWS Lambda hỗ trợ hai kiểu lời gọi hàm: đồng bộ và không đồng bộ. Với lời gọi không đồng bộ, sau khi hàm Lambda được kích hoạt, dịch vụ gọi hàm (chẳng hạn như S3) không đợi kết quả trả về ngay lập tức. Lambda sẽ xử lý sự kiện, và khi hoàn thành, nó sẽ gửi kết quả đến một dịch vụ khác (nếu được cấu hình) như SNS, SQS hoặc CloudWatch Logs.
Ví dụ từ hình:
Một S3 bucket sinh ra sự kiện (ví dụ: khi có tệp mới được tải lên), sự kiện này sẽ kích hoạt Lambda function để xử lý.
Mỗi khi có một tệp mới trong S3, Lambda sẽ được kích hoạt và thực thi xử lý tệp.
2. Concurrency (Tính đồng thời) và Throttling (Giới hạn)
Concurrency là khả năng Lambda có thể xử lý nhiều phiên bản của cùng một hàm cùng một lúc. Tuy nhiên, nếu lượng sự kiện vượt quá khả năng xử lý tính đồng thời của Lambda, các yêu cầu sẽ bị throttled (giới hạn).
Làm sao để Lambda bị Throttled?
- Nếu không còn đủ tính đồng thời để xử lý tất cả các sự kiện, các yêu cầu bổ sung sẽ bị giới hạn. Ví dụ: Nếu bạn có giới hạn 1000 phiên bản Lambda đồng thời và có 1001 sự kiện, sự kiện thứ 1001 sẽ bị giới hạn và không được xử lý ngay lập tức.
3. Xử lý khi bị Throttling với Asynchronous Invocation
Điều gì xảy ra khi Lambda bị giới hạn trong lời gọi không đồng bộ?
Khi một hàm Lambda bị giới hạn trong lời gọi không đồng bộ (bị throttle với lỗi 429 hoặc lỗi hệ thống 500), Lambda sẽ tự động thử lại (retry).
AWS Lambda sẽ trả sự kiện về hàng đợi của nó và thử thực thi lại trong vòng tối đa 6 giờ.
Thời gian giữa các lần thử lại sẽ tăng dần theo cấp số nhân. Thời gian bắt đầu từ 1 giây và có thể kéo dài đến 5 phút giữa các lần thử.
Ví dụ chi tiết:
Nếu một tệp được tải lên S3, nhưng Lambda không thể xử lý ngay lập tức vì vượt quá giới hạn, Lambda sẽ tự động thử lại sau 1 giây.
Nếu lần thử tiếp theo vẫn không thành công, nó sẽ tiếp tục thử lại sau thời gian dài hơn, cho đến khi đạt giới hạn tối đa là 5 phút giữa các lần thử.
4. Quản lý sự kiện và các vấn đề về tính đồng thời
Xử lý khi có quá nhiều sự kiện không đồng bộ
Giả sử bạn có một S3 bucket nơi người dùng thường xuyên tải lên các tệp lớn, và mỗi tệp mới sẽ kích hoạt Lambda xử lý. Khi số lượng tệp tải lên tăng nhanh, Lambda có thể gặp vấn đề về throttling nếu không có đủ tính đồng thời.
Giải pháp:
Tăng giới hạn tính đồng thời: Bạn có thể mở ticket hỗ trợ với AWS để tăng giới hạn tính đồng thời cho tài khoản của mình nếu thấy cần thiết.
Cấu hình Dead Letter Queue (DLQ): Nếu Lambda bị throttle quá nhiều lần và không thể xử lý sự kiện, bạn nên sử dụng DLQ (hàng đợi thư chết) để lưu trữ các sự kiện không thể xử lý và khắc phục sau đó.
Phân tách công việc: Nếu một hàm Lambda gặp phải quá nhiều sự kiện cùng lúc, bạn có thể tách công việc thành các hàm nhỏ hơn hoặc sử dụng các dịch vụ khác như SQS để làm trung gian điều phối sự kiện.
5. Tối ưu hóa Lambda để tránh throttling
Dưới đây là một số cách bạn có thể tối ưu hóa hàm Lambda của mình để tránh gặp phải tình trạng throttling quá nhiều:
Sử dụng Reserved Concurrency: Đặt giới hạn tính đồng thời cho từng hàm Lambda để đảm bảo rằng hàm không chiếm quá nhiều tài nguyên và ảnh hưởng đến các hàm khác.
Sử dụng Retry Logic: Khi sử dụng lời gọi không đồng bộ, hãy đảm bảo rằng Lambda được cấu hình để tự động thử lại trong trường hợp gặp lỗi hoặc bị giới hạn.
Cân nhắc thời gian xử lý của Lambda: Nếu một hàm Lambda xử lý quá lâu, hãy cân nhắc tách nhỏ công việc hoặc tối ưu hóa logic bên trong hàm để giảm thời gian thực thi.
6. Ví dụ cụ thể về tình huống
Tình huống 1: Tải tệp lên S3 và kích hoạt Lambda xử lý
Giả sử bạn có một bucket S3 để lưu trữ ảnh, và mỗi lần một người dùng tải ảnh lên, Lambda sẽ được kích hoạt để thực hiện các tác vụ như thay đổi kích thước hoặc thêm watermark. Khi có quá nhiều người dùng tải ảnh lên cùng lúc, Lambda có thể bị giới hạn vì vượt quá giới hạn tính đồng thời.
Giải pháp:
Bạn có thể sử dụng DLQ để lưu trữ các sự kiện không thể xử lý ngay lập tức.
Cấu hình Lambda để tự động thử lại nếu bị throttle và tối ưu hóa hàm Lambda để xử lý nhanh hơn.
Tình huống 2: Xử lý batch sự kiện từ S3 với tính đồng thời hạn chế
Giả sử bạn có một hàm Lambda xử lý sự kiện từ S3 nhưng chỉ có thể xử lý 10 tệp cùng lúc do giới hạn về tài nguyên hệ thống (ví dụ: hàm xử lý quá phức tạp). Bạn có thể cấu hình Reserved Concurrency để đảm bảo rằng hàm Lambda chỉ xử lý tối đa 10 sự kiện cùng lúc.
Giải pháp:
Sử dụng Reserved Concurrency để giới hạn số lượng phiên bản Lambda chạy đồng thời.
Nếu vượt quá giới hạn, Lambda sẽ thử lại sự kiện và lưu trữ trong DLQ nếu không thể xử lý trong thời gian quy định.
Kết luận
Hiểu rõ về Concurrency và cách Lambda xử lý các Asynchronous Invocations sẽ giúp bạn tránh được các sự cố về throttling và tối ưu hóa ứng dụng của mình. Bạn cần nắm rõ cách quản lý tính đồng thời và cấu hình lại Lambda nếu cần, như việc sử dụng DLQ hoặc tăng giới hạn concurrency khi cần thiết.
WS Lambda: Cold Starts và Provisioned Concurrency, hai yếu tố ảnh hưởng đến hiệu suất và thời gian phản hồi của hàm Lambda. Đây là những kiến thức rất cần thiết để hiểu cách Lambda hoạt động, và cũng là một phần không thể thiếu trong việc chuẩn bị cho kỳ thi AWS Certified Developer – Associate.
Hãy cùng mình phân tích chi tiết các khái niệm này và kèm theo các ví dụ minh họa dễ hiểu.
1. Cold Start là gì?
Cold Start xảy ra khi AWS Lambda phải khởi tạo một instance mới của hàm Lambda để phục vụ yêu cầu. Khi một hàm Lambda chưa có bất kỳ phiên bản nào đang chạy, hoặc tất cả các phiên bản hiện tại đều bận xử lý các yêu cầu khác, AWS sẽ khởi động một instance Lambda mới. Quá trình này đòi hỏi Lambda phải:
Load mã nguồn của hàm Lambda.
Khởi tạo các phụ thuộc bên ngoài (nếu có), ví dụ như các thư viện SDK hoặc các kết nối cơ sở dữ liệu.
Chạy đoạn mã khởi tạo bên ngoài
handler
của Lambda (được gọi là quá trình init).
Điều này dẫn đến một độ trễ (latency) cao hơn cho yêu cầu đầu tiên vì phải chờ instance mới được khởi động.
Tại sao Cold Start lại là vấn đề?
Cold Start gây ra thời gian phản hồi chậm hơn cho yêu cầu đầu tiên. Nếu ứng dụng của bạn cần phản hồi nhanh, Cold Start có thể làm giảm hiệu suất và trải nghiệm người dùng.
Ví dụ: Nếu hàm Lambda của bạn yêu cầu tải một lượng lớn thư viện SDK hoặc cần thiết lập kết nối với cơ sở dữ liệu RDS, thời gian khởi động có thể kéo dài hơn bình thường (vài giây hoặc lâu hơn).
Khi nào Cold Start xảy ra?
Cold Start xảy ra khi Lambda khởi tạo một instance mới để xử lý yêu cầu.
Cold Start thường gặp khi:
Lambda chưa có instance nào được chạy.
Các phiên bản đang chạy đã bận xử lý các yêu cầu khác.
Lambda bị scale out để đáp ứng yêu cầu tăng đột ngột.
2. Provisioned Concurrency là gì?
Để giảm thiểu hoặc loại bỏ hoàn toàn Cold Start, AWS đã giới thiệu khái niệm Provisioned Concurrency. Đây là một tính năng cho phép bạn khởi tạo sẵn (pre-warm) một số lượng nhất định các instance Lambda trước khi có yêu cầu. Điều này có nghĩa là các instance Lambda luôn sẵn sàng và không cần khởi tạo từ đầu, giúp giảm thiểu độ trễ (latency) cho các yêu cầu.
Cách hoạt động của Provisioned Concurrency:
Concurrency (tính đồng thời) được phân bổ trước (allocate in advance) cho hàm Lambda của bạn.
Khi yêu cầu đến, các phiên bản Lambda đã được khởi tạo sẵn và không cần trải qua quá trình Cold Start.
Điều này đảm bảo rằng tất cả các yêu cầu đều được xử lý với độ trễ thấp.
Ví dụ về Provisioned Concurrency:
Giả sử bạn có một ứng dụng web có lưu lượng truy cập tăng đột biến vào một khung giờ nhất định trong ngày (ví dụ, buổi sáng từ 9:00 đến 11:00). Thay vì phải chịu đựng độ trễ từ Cold Start trong khoảng thời gian này, bạn có thể cấu hình Provisioned Concurrency để đảm bảo rằng vào khung giờ cao điểm, Lambda đã khởi tạo sẵn một số phiên bản để xử lý yêu cầu ngay lập tức.
3. Ứng dụng của Provisioned Concurrency và Auto Scaling
Auto Scaling có thể được sử dụng cùng với Provisioned Concurrency để quản lý tính đồng thời dựa trên lưu lượng thực tế. Bạn có thể thiết lập lịch biểu (schedule) hoặc dựa trên mức sử dụng mục tiêu (target utilization) để tự động tăng/giảm số lượng phiên bản được khởi tạo sẵn.
Ví dụ:
Nếu bạn biết rằng lưu lượng của bạn tăng cao vào khoảng thời gian buổi sáng, bạn có thể thiết lập Application Auto Scaling để kích hoạt Provisioned Concurrency vào khung giờ này.
Khi lưu lượng giảm, Provisioned Concurrency có thể giảm xuống, giúp bạn tiết kiệm chi phí.
4. Giảm thiểu Cold Start trong VPC
AWS đã có những cải tiến lớn về Cold Starts trong VPC từ tháng 10 và tháng 11 năm 2019. Trước đây, việc sử dụng Lambda trong VPC gây ra thời gian Cold Start dài hơn vì phải thiết lập các kết nối mạng riêng tư (ENI - Elastic Network Interface). Tuy nhiên, AWS đã tối ưu hóa quá trình này, giúp giảm đáng kể thời gian Cold Start cho các hàm Lambda chạy trong VPC.
5. Ví dụ cụ thể về Cold Start và Provisioned Concurrency
Tình huống 1: Cold Start trong ứng dụng web
Giả sử bạn có một ứng dụng web bán hàng trực tuyến. Mỗi khi người dùng truy cập trang web, yêu cầu sẽ được gửi đến Lambda để lấy thông tin sản phẩm từ cơ sở dữ liệu. Nếu không có Provisioned Concurrency, các yêu cầu đầu tiên có thể bị chậm do Cold Start khi Lambda phải thiết lập kết nối đến cơ sở dữ liệu và tải các thư viện cần thiết.
Giải pháp: Sử dụng Provisioned Concurrency để khởi tạo trước các phiên bản Lambda nhằm đảm bảo rằng ứng dụng của bạn luôn phản hồi nhanh chóng, ngay cả với yêu cầu đầu tiên.
Tình huống 2: Sử dụng Auto Scaling với Provisioned Concurrency
Giả sử bạn có một hệ thống báo cáo mà người dùng thường truy cập nhiều vào buổi sáng. Bạn có thể cấu hình Application Auto Scaling để tự động tăng số lượng phiên bản Lambda được khởi tạo trước vào khung giờ cao điểm. Khi nhu cầu giảm sau 11 giờ sáng, Auto Scaling sẽ tự động giảm số lượng phiên bản để tối ưu hóa chi phí.
6. Kết luận
Cold Start là một vấn đề phổ biến khi sử dụng AWS Lambda, đặc biệt là với các ứng dụng yêu cầu phản hồi nhanh. Tuy nhiên, với Provisioned Concurrency, bạn có thể loại bỏ hoàn toàn Cold Start và đảm bảo rằng hàm Lambda của bạn luôn phản hồi nhanh chóng cho mọi yêu cầu. Hãy cân nhắc sử dụng Application Auto Scaling để quản lý tính đồng thời một cách thông minh và tối ưu hóa chi phí khi chạy ứng dụng trên Lambda.
1. Reserved Concurrency là gì?
Reserved Concurrency (Tính đồng thời được đặt trước) là tính năng cho phép bạn giới hạn số lượng phiên bản Lambda chạy đồng thời cho một hàm Lambda cụ thể. Điều này đảm bảo rằng một hàm Lambda sẽ không thể vượt qua giới hạn mà bạn đã định trước, giúp bảo vệ các hàm Lambda khác trong tài khoản của bạn khỏi việc bị chiếm hết tài nguyên tính đồng thời.
Lợi ích của Reserved Concurrency:
- Bảo vệ các chức năng quan trọng: Nếu một hàm Lambda gặp phải quá nhiều yêu cầu đồng thời, nó có thể chiếm hết toàn bộ tài nguyên tính đồng thời, khiến các hàm khác không thể xử lý. Reserved Concurrency giúp giới hạn điều này, đảm bảo mỗi hàm Lambda chỉ sử dụng đúng số lượng phiên bản đồng thời mà bạn đã quy định.
Ví dụ từ hình ảnh:
my-function-DEV và my-function-PROD: Bạn có thể thấy hai hàm Lambda này có Reserved Concurrency, tức là có một phần tài nguyên đã được đặt trước cho chúng, giúp bảo vệ các chức năng quan trọng của chúng khỏi việc bị chiếm hết tài nguyên bởi các hàm khác.
Other functions: Các hàm Lambda khác trong tài khoản sẽ phải chia sẻ số tài nguyên tính đồng thời còn lại (phần "Unreserved Concurrency"). Nếu có quá nhiều yêu cầu đến các hàm này, có thể dẫn đến Throttling (giới hạn).
2. Provisioned Concurrency là gì?
Provisioned Concurrency (Tính đồng thời được chuẩn bị trước) là một tính năng mạnh mẽ hơn Reserved Concurrency. Nó không chỉ đảm bảo số lượng phiên bản đồng thời có sẵn, mà còn khởi tạo trước các phiên bản Lambda. Điều này giúp loại bỏ hoàn toàn vấn đề Cold Start, đảm bảo rằng các yêu cầu Lambda sẽ luôn được xử lý ngay lập tức mà không phải chờ đợi việc khởi tạo phiên bản mới.
Lợi ích của Provisioned Concurrency:
Loại bỏ Cold Start: Khi có Provisioned Concurrency, AWS sẽ khởi tạo trước các phiên bản Lambda, đảm bảo rằng chúng luôn sẵn sàng để xử lý các yêu cầu ngay lập tức.
Tối ưu hóa hiệu suất: Tất cả các yêu cầu đều được phản hồi với độ trễ rất thấp.
Ví dụ từ hình ảnh:
my-function-PROD: Hàm Lambda này không chỉ có Reserved Concurrency, mà còn có Provisioned Concurrency. Điều này có nghĩa là AWS sẽ luôn có một số lượng phiên bản Lambda của hàm này được khởi tạo trước và sẵn sàng phục vụ yêu cầu ngay lập tức.
my-function-DEV: Hàm này chỉ có Reserved Concurrency mà không có Provisioned Concurrency, điều này có nghĩa là các phiên bản của nó không được khởi tạo trước. Điều này có thể dẫn đến Cold Start khi Lambda cần phải khởi tạo phiên bản mới.
3. Phân biệt Reserved Concurrency và Provisioned Concurrency
Reserved Concurrency:
Giới hạn số lượng phiên bản đồng thời có thể chạy cho một hàm Lambda.
Bảo vệ tài nguyên để đảm bảo hàm Lambda không sử dụng quá nhiều phiên bản đồng thời.
Tuy nhiên, Cold Start vẫn có thể xảy ra nếu Lambda phải khởi tạo phiên bản mới.
Provisioned Concurrency:
Không chỉ giới hạn số lượng phiên bản, mà còn khởi tạo trước các phiên bản Lambda.
Loại bỏ Cold Start hoàn toàn, đảm bảo tất cả các yêu cầu được phản hồi ngay lập tức.
4. Tối ưu hóa chi phí và hiệu suất
Provisioned Concurrency mang lại hiệu suất cao hơn nhưng cũng đồng nghĩa với việc chi phí tăng lên, vì AWS sẽ phải duy trì các phiên bản Lambda đã khởi tạo sẵn ngay cả khi không có yêu cầu. Do đó, để tối ưu hóa chi phí, bạn có thể kết hợp Provisioned Concurrency với Auto Scaling, giúp điều chỉnh số lượng phiên bản khởi tạo sẵn dựa trên lịch hoặc lưu lượng thực tế.
Ví dụ:
- Nếu bạn biết rằng ứng dụng của mình có lưu lượng cao vào buổi sáng từ 9:00 đến 12:00, bạn có thể cấu hình Auto Scaling để chỉ kích hoạt Provisioned Concurrency trong khung giờ này. Sau 12:00, số lượng phiên bản khởi tạo sẵn có thể giảm xuống để tiết kiệm chi phí.
5. Khi nào nên sử dụng Reserved Concurrency và Provisioned Concurrency?
Reserved Concurrency: Nên sử dụng khi bạn cần đảm bảo rằng một hàm Lambda quan trọng không bị gián đoạn do các hàm Lambda khác sử dụng quá nhiều tài nguyên tính đồng thời.
Provisioned Concurrency: Sử dụng khi bạn cần loại bỏ Cold Start và đảm bảo rằng các yêu cầu được phản hồi ngay lập tức với độ trễ thấp nhất, đặc biệt quan trọng trong các ứng dụng thời gian thực hoặc có yêu cầu phản hồi nhanh.
6. Ví dụ thực tế
Tình huống 1: Ứng dụng web bán hàng trực tuyến
Giả sử bạn có một ứng dụng bán hàng trực tuyến với hai môi trường: DEV và PROD. Môi trường PROD rất quan trọng vì phục vụ khách hàng trực tiếp, và bạn cần đảm bảo rằng hệ thống luôn phản hồi nhanh. Bạn có thể:
Đặt Reserved Concurrency cho cả hai môi trường: Điều này đảm bảo cả môi trường DEV và PROD đều có một lượng tài nguyên nhất định.
Sử dụng Provisioned Concurrency cho môi trường PROD: Điều này đảm bảo các yêu cầu từ khách hàng sẽ không gặp phải Cold Start, giúp trải nghiệm người dùng luôn mượt mà.
Tình huống 2: Ứng dụng báo cáo nội bộ
Với một ứng dụng báo cáo nội bộ mà không yêu cầu phản hồi nhanh, bạn có thể chỉ sử dụng Reserved Concurrency để đảm bảo hàm Lambda không chiếm quá nhiều tài nguyên, nhưng không cần sử dụng Provisioned Concurrency vì bạn có thể chấp nhận thời gian Cold Start.
Kết luận
Hiểu rõ sự khác biệt giữa Reserved Concurrency và Provisioned Concurrency là yếu tố quan trọng trong việc quản lý và tối ưu hóa ứng dụng AWS Lambda của bạn. Reserved Concurrency giúp bảo vệ tài nguyên của hàm Lambda, trong khi Provisioned Concurrency mang lại hiệu suất cao hơn bằng cách loại bỏ Cold Start.
1. Lambda Function Dependencies là gì?
Lambda function dependencies là các thư viện hoặc package mà hàm Lambda của bạn cần sử dụng trong quá trình thực thi. Ví dụ, nếu hàm Lambda của bạn cần kết nối đến cơ sở dữ liệu hoặc sử dụng SDK của AWS (như AWS X-Ray SDK để theo dõi), bạn sẽ cần bao gồm các thư viện này khi triển khai hàm Lambda.
Tại sao cần chú ý đến dependencies?
Khi triển khai một hàm Lambda, mã nguồn của bạn không thể hoạt động độc lập nếu nó phụ thuộc vào các thư viện bên ngoài. Bạn cần phải cài đặt các thư viện đó và gói chúng cùng với mã nguồn của bạn để đảm bảo Lambda có thể sử dụng chúng khi thực thi.
2. Cách cài đặt và đóng gói các thư viện (dependencies)
Node.js (JavaScript):
Đối với Node.js, bạn sử dụng công cụ npm (Node Package Manager) để cài đặt các package vào thư mục node_modules.
Khi bạn cài đặt các package bằng cách sử dụng lệnh
npm install
, một thư mục node_modules sẽ được tạo ra, chứa tất cả các thư viện mà hàm Lambda của bạn cần.Sau đó, bạn cần nén toàn bộ mã nguồn và thư mục node_modules vào một file
.zip
và tải lên AWS Lambda.
Ví dụ:
Giả sử bạn đang sử dụng một package Node.js để kết nối đến cơ sở dữ liệu MongoDB. Bạn sẽ chạy lệnh:
bash
Copy code
npm install mongodb
Sau đó, thư mục node_modules chứa package mongodb
sẽ được tạo. Bạn cần nén cả mã nguồn và node_modules vào một file .zip
và tải lên Lambda.
Python:
Đối với Python, bạn sử dụng lệnh pip với tùy chọn -target để cài đặt các package vào một thư mục cụ thể.
Sau đó, bạn cũng cần nén thư mục chứa các package cùng với mã nguồn và tải lên Lambda.
Ví dụ:
Nếu bạn đang sử dụng boto3 để làm việc với AWS SDK trong Python, bạn có thể chạy lệnh sau để cài đặt:
bash
Copy code
pip install boto3 --target ./my-folder
Thư mục my-folder
sẽ chứa tất cả các dependencies cần thiết. Sau đó, bạn cần nén cả mã nguồn và thư mục my-folder
vào file .zip
và tải lên Lambda.
Java:
Đối với Java, bạn cần bao gồm các file
.jar
chứa các thư viện mà bạn sử dụng trong project.Bạn cần chắc chắn rằng tất cả các file
.jar
liên quan được đóng gói cùng với mã nguồn trước khi triển khai lên Lambda.
Ví dụ:
Nếu bạn đang sử dụng AWS SDK cho Java, bạn cần thêm các file .jar
vào dự án và đảm bảo rằng chúng được bao gồm trong gói nén khi tải lên Lambda.
3. Giới hạn dung lượng của Lambda
Khi bạn triển khai hàm Lambda, có một số giới hạn về dung lượng của file zip mà bạn có thể tải trực tiếp lên Lambda:
Nếu file zip của bạn dưới 50MB, bạn có thể tải trực tiếp lên Lambda qua AWS Console.
Nếu file zip của bạn lớn hơn 50MB, bạn cần tải lên S3 (Amazon Simple Storage Service) trước, sau đó chỉ định URL của file này cho Lambda.
Lưu ý về dung lượng:
Nếu hàm Lambda của bạn sử dụng nhiều dependencies lớn, chẳng hạn như nhiều thư viện cho machine learning hoặc xử lý hình ảnh, file zip có thể vượt quá 50MB. Trong trường hợp đó, bạn cần tải file lên S3 trước khi triển khai.
4. Native Libraries (Thư viện gốc)
Nếu hàm Lambda của bạn sử dụng các thư viện gốc (native libraries) mà cần biên dịch (compile) trên hệ điều hành Linux, bạn phải chắc chắn rằng các thư viện này được biên dịch trên Amazon Linux. AWS Lambda chạy trên một môi trường Amazon Linux, vì vậy mọi thư viện cần được biên dịch để có thể hoạt động trên hệ điều hành này.
5. AWS SDK tích hợp sẵn
Một lợi thế khi làm việc với AWS Lambda là AWS SDK (Software Development Kit) đã được tích hợp sẵn trong mỗi môi trường Lambda. Điều này có nghĩa là nếu bạn chỉ cần tương tác với các dịch vụ AWS (ví dụ: S3, DynamoDB, SQS) thông qua AWS SDK, bạn không cần phải cài đặt thêm bất kỳ thư viện nào, vì AWS SDK đã có sẵn trong môi trường Lambda.
6. Ví dụ thực tế về sử dụng dependencies trong Lambda
Tình huống 1: Kết nối cơ sở dữ liệu với Lambda
Giả sử bạn muốn sử dụng hàm Lambda để kết nối với một cơ sở dữ liệu MySQL. Bạn sẽ cần các thư viện bên ngoài để làm điều này, ví dụ:
Với Node.js, bạn sẽ sử dụng package
mysql
:bash Copy code npm install mysql
Sau đó, đóng gói mã nguồn và thư mục node_modules và tải lên Lambda.
Với Python, bạn sẽ sử dụng thư viện
mysql-connector
:bash Copy code pip install mysql-connector --target ./my-folder
Sau đó, nén thư mục
my-folder
và mã nguồn của bạn rồi tải lên Lambda.
Tình huống 2: Theo dõi bằng AWS X-Ray
Nếu bạn cần tích hợp AWS X-Ray để theo dõi và giám sát các yêu cầu qua hàm Lambda của mình, bạn sẽ cần cài đặt AWS X-Ray SDK cùng với mã nguồn.
Với Node.js:
bash Copy code npm install aws-xray-sdk
Với Python:
bash Copy code pip install aws-xray-sdk --target ./my-folder
Sau đó, bạn nén thư mục chứa mã nguồn và các package đã cài đặt rồi tải lên Lambda để sử dụng.
Kết luận
Hiểu rõ cách quản lý dependencies trong AWS Lambda là điều rất quan trọng để đảm bảo rằng hàm Lambda của bạn có thể hoạt động trơn tru với các thư viện bên ngoài. Bằng cách cài đặt đúng các package và đóng gói chúng cùng với mã nguồn, bạn có thể triển khai các hàm Lambda phức tạp một cách dễ dàng.
tạo hàm Lambda trong CloudFormation bằng cách sử dụng inline code. Đây là một kỹ thuật giúp triển khai các hàm Lambda đơn giản trực tiếp trong file CloudFormation template mà không cần tải mã nguồn lên S3 hay sử dụng các tệp zip lớn. Tuy nhiên, cách này cũng có những giới hạn mà bạn cần hiểu rõ để áp dụng phù hợp.
Hãy cùng mình phân tích chi tiết về cách tạo Lambda với CloudFormation theo hình ảnh và giải thích từng phần để dễ hiểu hơn.
1. CloudFormation là gì?
AWS CloudFormation là một dịch vụ giúp bạn mô tả và quản lý cơ sở hạ tầng dưới dạng code. Bạn có thể định nghĩa toàn bộ tài nguyên AWS của mình như EC2, S3, Lambda,... trong một file template bằng định dạng JSON hoặc YAML, sau đó triển khai template này để AWS tự động tạo và cấu hình các tài nguyên theo như bạn mô tả.
2. Lambda function inline là gì?
Một hàm Lambda inline là hàm mà mã nguồn của nó được viết trực tiếp trong file CloudFormation template. Điều này thường áp dụng cho các hàm Lambda đơn giản với ít dòng mã. Trong trường hợp này, mã nguồn được bao gồm trong thuộc tính Code.ZipFile của tài nguyên AWS::Lambda::Function trong template.
Ví dụ từ hình ảnh:
Hình ảnh cung cấp một mẫu CloudFormation template bằng YAML với một hàm Lambda đơn giản được viết trực tiếp (inline). Cụ thể:
Phần thuộc tính Code.ZipFile chứa mã Python đơn giản.
Hàm Lambda này chỉ cần import os và sử dụng một biến môi trường để kết nối cơ sở dữ liệu.
yaml
Copy code
Resources:
primer:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.x
Role: arn:aws:iam::123456789012:role/lambda-role
Handler: index.handler
Code:
ZipFile: |
import os
DB_URL = os.getenv("DB_URL")
db_client = db.connect(DB_URL)
def handler(event, context):
user = db_client.get(user_id = event["user_id"])
return user
3. Các lưu ý quan trọng về Lambda inline
Ưu điểm của Lambda inline:
Đơn giản: Bạn có thể viết trực tiếp mã nguồn của Lambda trong file CloudFormation mà không cần xử lý thêm các bước như nén file hoặc tải lên S3.
Nhanh chóng: Đối với các chức năng đơn giản, cách này rất tiện lợi và giúp việc triển khai trở nên dễ dàng hơn mà không cần quá nhiều bước xử lý file mã nguồn.
Giới hạn của Lambda inline:
Không hỗ trợ dependencies (phụ thuộc): Bạn không thể sử dụng các thư viện ngoài (như SDK, thư viện bên thứ ba) khi sử dụng inline code. Điều này giới hạn khả năng của Lambda nếu bạn cần sử dụng thêm các package.
Dung lượng mã: Do mã nguồn được viết trực tiếp trong file CloudFormation, cách này chỉ phù hợp cho các hàm đơn giản với số lượng dòng mã ít. Nếu mã quá dài, nó sẽ làm file template trở nên phức tạp và khó bảo trì.
Ví dụ về hạn chế:
Nếu bạn cần sử dụng một thư viện như boto3 hoặc pandas trong hàm Lambda, bạn không thể làm điều đó với inline code, vì bạn không thể cài đặt các thư viện này trong file CloudFormation. Thay vào đó, bạn phải tải mã nguồn cùng với các dependencies lên S3 dưới dạng tệp zip.
4. Cách sử dụng CloudFormation để tạo Lambda với mã nguồn lớn
Khi bạn có một hàm Lambda phức tạp và cần sử dụng nhiều thư viện hoặc dependencies, bạn sẽ không thể sử dụng inline code. Trong trường hợp này, bạn cần phải:
Viết mã nguồn của hàm Lambda và các thư viện mà hàm phụ thuộc vào.
Đóng gói (zip) mã nguồn và các dependencies.
Tải lên S3 file zip chứa mã nguồn và thư viện.
Trong file CloudFormation, bạn cần sử dụng thuộc tính Code.S3Bucket và Code.S3Key để chỉ định file zip đã tải lên S3.
Ví dụ:
Giả sử bạn có một hàm Lambda sử dụng boto3 để tương tác với S3, bạn cần tải file zip của mã nguồn lên S3 như sau:
yaml
Copy code
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.x
Handler: index.handler
Role: arn:aws:iam::123456789012:role/lambda-role
Code:
S3Bucket: my-lambda-functions
S3Key: my-function-code.zip
Trong ví dụ này:
S3Bucket là bucket nơi bạn đã tải file zip chứa mã nguồn của Lambda.
S3Key là tên file zip mà bạn đã tải lên.
5. Khi nào nên sử dụng Lambda inline?
Bạn nên sử dụng Lambda inline khi:
Hàm Lambda của bạn rất đơn giản và không phụ thuộc vào các thư viện bên ngoài.
Bạn muốn triển khai nhanh và không cần phải tải mã nguồn lên S3.
Mã nguồn của bạn ngắn gọn, chẳng hạn như một vài dòng mã để xử lý sự kiện đơn giản.
Ví dụ tình huống:
Giả sử bạn cần một hàm Lambda để thực hiện một chuyển hướng đơn giản hoặc xử lý chuỗi từ một sự kiện SNS. Trong trường hợp này, hàm Lambda chỉ cần một vài dòng mã để thực hiện logic xử lý và không cần phụ thuộc vào các thư viện bên ngoài. Đây là tình huống hoàn hảo để sử dụng inline code.
6. Kết luận
Sử dụng inline code trong CloudFormation là một cách đơn giản và hiệu quả để triển khai các hàm Lambda nhỏ gọn, không có nhiều phụ thuộc. Tuy nhiên, với các ứng dụng phức tạp hơn, bạn sẽ cần triển khai mã nguồn thông qua S3 và nén toàn bộ code cũng như dependencies. Hiểu rõ giới hạn và khả năng của từng phương pháp sẽ giúp bạn triển khai các hàm Lambda một cách hiệu quả và phù hợp với yêu cầu của ứng dụng.
AWS Lambda với CloudFormation thông qua S3. Điều này rất quan trọng khi triển khai các hàm Lambda phức tạp và khi cần sử dụng nhiều tài khoản AWS để chia sẻ và tái sử dụng mã nguồn của Lambda. Dưới đây là giải thích chi tiết về từng phần trong hình ảnh, kèm theo các ví dụ minh họa để bạn dễ hiểu hơn, giúp chuẩn bị tốt cho kỳ thi AWS Certified Developer – Associate.
1. CloudFormation tích hợp với Lambda qua S3
Tại sao cần dùng S3 với Lambda?
Trong những trường hợp mà hàm Lambda của bạn có mã nguồn và các thư viện phụ thuộc (dependencies) lớn, bạn không thể sử dụng inline code như đã nói ở phần trước. Thay vào đó, bạn cần:
Viết mã nguồn Lambda và đóng gói các thư viện phụ thuộc vào file
.zip
.Tải file
.zip
này lên S3.Trong file CloudFormation template, bạn phải chỉ định đường dẫn đến tệp
.zip
đã tải lên S3 thông qua các thuộc tính như S3Bucket, S3Key, và S3ObjectVersion.
Ví dụ từ hình ảnh:
File template YAML tạo một hàm Lambda, với mã nguồn của Lambda được tải lên S3:
yaml
Copy code
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: arn:aws:iam::123456789012:role/lambda-role
Code:
S3Bucket: my-bucket
S3Key: function.zip
S3ObjectVersion: String
Runtime: nodejs12.x
Trong ví dụ này:
S3Bucket: Đây là bucket trong S3 nơi bạn đã tải file
.zip
của Lambda.S3Key: Đây là tên tệp
.zip
chứa mã nguồn của Lambda.S3ObjectVersion: Nếu bucket của bạn có versioning (phiên bản hóa) bật, bạn có thể chỉ định phiên bản cụ thể của file
.zip
để sử dụng.
Lưu ý:
- Nếu bạn cập nhật mã nguồn Lambda trong S3, nhưng không cập nhật thông tin trong CloudFormation (như S3Bucket, S3Key hoặc S3ObjectVersion), CloudFormation sẽ không cập nhật hàm Lambda của bạn. Điều này rất quan trọng khi triển khai mã nguồn và cần phải đồng bộ phiên bản của mã giữa S3 và CloudFormation.
2. Triển khai Lambda qua S3 cho nhiều tài khoản AWS
Trong môi trường doanh nghiệp lớn, có thể bạn sẽ cần chia sẻ mã nguồn Lambda giữa nhiều tài khoản AWS. Ví dụ, bạn có thể tải mã nguồn Lambda lên S3 bucket trong tài khoản A nhưng triển khai nó ở tài khoản B và tài khoản C.
Cách triển khai qua nhiều tài khoản:
Tài khoản 1 (Account 1): Đây là tài khoản chứa S3 bucket có mã nguồn Lambda. Bạn cần thiết lập bucket policy để cho phép các tài khoản khác truy cập vào bucket này.
Tài khoản 2 và 3: Đây là các tài khoản sử dụng CloudFormation để tạo hàm Lambda bằng mã nguồn từ S3 bucket của tài khoản 1.
Cấu hình Bucket Policy:
Để chia sẻ mã nguồn Lambda từ Account 1 cho các tài khoản khác, bạn phải cập nhật Bucket Policy trên S3 bucket trong Account 1 để cho phép lệnh get và list từ các tài khoản khác:
json
Copy code
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::ACCOUNT2_ID:root",
"arn:aws:iam::ACCOUNT3_ID:root"
]
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-lambda-bucket/*"
]
}
]
}
Principal: Liệt kê các tài khoản AWS khác (Account 2, Account 3) được phép truy cập vào S3 bucket trong tài khoản 1.
Action: Chỉ định các hành động mà các tài khoản khác có thể thực hiện, như GetObject để tải file
.zip
và ListBucket để liệt kê các tệp trong bucket.Resource: Đây là ARN của S3 bucket chứa mã nguồn Lambda.
Ví dụ:
- Tài khoản 2 và 3: Sau khi thiết lập Bucket Policy, các tài khoản này có thể sử dụng CloudFormation để triển khai hàm Lambda từ mã nguồn trong S3 bucket của tài khoản 1. Tệp CloudFormation trong tài khoản 2 hoặc tài khoản 3 sẽ trỏ đến file
.zip
trong S3 của tài khoản 1, như sau:
yaml
Copy code
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: arn:aws:iam::123456789012:role/lambda-role
Code:
S3Bucket: my-lambda-bucket
S3Key: function.zip
S3ObjectVersion: Version_ID
Runtime: nodejs12.x
3. Các trường hợp sử dụng thực tế
Tình huống 1: Chia sẻ mã nguồn giữa nhiều môi trường
Giả sử bạn có môi trường dev và prod trong hai tài khoản AWS khác nhau. Bạn muốn đảm bảo rằng cả hai môi trường đều sử dụng cùng một mã nguồn Lambda từ S3. Trong trường hợp này, bạn có thể:
Tải mã nguồn Lambda lên S3 bucket trong tài khoản 1 (môi trường dev).
Cho phép tài khoản 2 (môi trường prod) sử dụng mã nguồn này để triển khai Lambda, nhờ vào bucket policy phù hợp.
Tình huống 2: Triển khai trên nhiều tài khoản của doanh nghiệp
Trong một tổ chức lớn, có thể bạn sẽ cần triển khai cùng một Lambda trên nhiều tài khoản AWS khác nhau. Việc tải mã nguồn Lambda lên một S3 bucket duy nhất trong một tài khoản và chia sẻ bucket này cho các tài khoản khác giúp bạn tiết kiệm thời gian và dễ dàng quản lý phiên bản của mã nguồn.
4. Lưu ý quan trọng khi triển khai Lambda qua S3
Bucket Policy phải được cấu hình chính xác: Nếu bạn không cấp đúng quyền truy cập, các tài khoản khác sẽ không thể truy cập vào mã nguồn trong bucket của bạn.
S3ObjectVersion rất quan trọng: Nếu bạn bật versioning trên S3 bucket, bạn cần chỉ định phiên bản cụ thể của mã nguồn để tránh việc sử dụng sai phiên bản khi triển khai.
Cập nhật CloudFormation khi mã nguồn thay đổi: Nếu bạn cập nhật mã nguồn trong S3 mà không cập nhật CloudFormation template (đặc biệt là thuộc tính S3Key hoặc S3ObjectVersion), hàm Lambda sẽ không được cập nhật.
Kết luận
Triển khai Lambda qua S3 trong CloudFormation là cách phổ biến và hiệu quả khi bạn có mã nguồn phức tạp hoặc cần chia sẻ giữa nhiều tài khoản AWS. Việc hiểu rõ cách sử dụng S3 bucket, bucket policy, và cách đồng bộ phiên bản mã nguồn giữa S3 và CloudFormation sẽ giúp bạn quản lý hệ thống một cách chuyên nghiệp và linh hoạt hơn.
1. Tổng quan về Lambda Container Images
Container Images là gì?
Một container image là một gói phần mềm tự cung cấp (self-contained package), bao gồm mã nguồn ứng dụng cùng với tất cả các thư viện phụ thuộc và cấu hình môi trường cần thiết để chạy ứng dụng. Đối với Lambda, bạn có thể triển khai các container image có kích thước tối đa lên đến 10GB, so với giới hạn 50MB của mã nguồn Lambda truyền thống.
Sử dụng ECR (Elastic Container Registry)
Container images sẽ được tải lên Amazon Elastic Container Registry (ECR), nơi mà Lambda có thể truy cập để triển khai các image này. ECR là một dịch vụ quản lý container, cho phép bạn lưu trữ, chia sẻ và triển khai các container image một cách an toàn.
Các lợi ích của Lambda Container Images:
Đóng gói các phụ thuộc phức tạp: Nếu bạn có các ứng dụng phức tạp yêu cầu nhiều thư viện bên ngoài, bạn có thể đóng gói tất cả vào trong container, giúp việc triển khai dễ dàng hơn.
Hỗ trợ nhiều ngôn ngữ: AWS cung cấp base images cho nhiều ngôn ngữ như Python, Node.js, Java, .NET, Go, Ruby. Bạn cũng có thể tự tạo image của riêng mình miễn là nó tuân thủ Lambda Runtime API.
Thử nghiệm cục bộ: Bạn có thể sử dụng Lambda Runtime Interface Emulator để thử nghiệm container cục bộ trước khi triển khai, giúp tiết kiệm thời gian phát triển.
Ví dụ từ hình ảnh:
Mã nguồn của bạn được đóng gói trong container cùng với các thư viện và dữ liệu. Sau đó, bạn build container, publish lên ECR, và triển khai lên Lambda. Quy trình này rất đơn giản và hiệu quả khi bạn cần quản lý môi trường phức tạp.
2. Ví dụ tạo Lambda Container Image
Trong phần dưới, bạn có thể thấy một ví dụ về việc tạo một container image từ base image do AWS cung cấp:
dockerfile
Copy code
# Sử dụng một image cơ bản (base image) có tích hợp Lambda Runtime API
FROM amazon/aws-lambda-nodejs:12
# Copy mã nguồn ứng dụng và các file cần thiết vào container
COPY app.js package*.json ./
# Cài đặt các thư viện phụ thuộc trong container
RUN npm install
# Chỉ định hàm Lambda cần được gọi khi chức năng Lambda được kích hoạt
CMD ["app.lambdaHandler"]
Giải thích các bước:
FROM: Lệnh này sử dụng một base image do AWS cung cấp, đã tích hợp Lambda Runtime API cho Node.js. Bạn có thể thay đổi image cho phù hợp với ngôn ngữ lập trình của mình.
COPY: Sao chép mã nguồn ứng dụng (
app.js
) và file cấu hình thư viện (package.json
) vào container.RUN npm install: Cài đặt tất cả các thư viện và dependencies bên trong container.
CMD: Xác định hàm Lambda sẽ được chạy khi có sự kiện kích hoạt Lambda. Trong trường hợp này, đó là
lambdaHandler
trong fileapp.js
.
Triển khai lên ECR và Lambda:
Sau khi tạo xong container, bạn có thể build và push container lên ECR.
Sau đó, bạn chỉ cần triển khai container này lên Lambda và AWS sẽ tự động quản lý việc chạy container cho bạn.
3. Khi nào nên sử dụng Lambda Container Images?
Sử dụng container image cho Lambda rất hữu ích khi:
Ứng dụng của bạn phức tạp và cần nhiều thư viện hoặc dữ liệu lớn mà không thể đóng gói trong giới hạn 50MB của Lambda truyền thống.
Cần tùy chỉnh môi trường chạy: Nếu bạn cần cài đặt các công cụ hoặc phần mềm không có sẵn trong môi trường Lambda mặc định, container cho phép bạn làm điều này.
Phát triển theo quy trình DevOps: Bạn có thể sử dụng Docker để xây dựng, thử nghiệm và triển khai ứng dụng theo quy trình CI/CD, giúp việc phát triển và triển khai trở nên nhất quán và dễ dàng hơn.
Ví dụ thực tế:
Giả sử bạn có một ứng dụng Machine Learning sử dụng TensorFlow và yêu cầu nhiều file thư viện lớn. Thay vì phải quản lý từng thư viện riêng lẻ, bạn có thể đóng gói toàn bộ ứng dụng và các thư viện vào một container image. Sau đó, triển khai container này lên Lambda để thực hiện các tác vụ tính toán nặng.
4. Thử nghiệm cục bộ với Lambda Runtime Interface Emulator
Một lợi ích lớn của Lambda Container là bạn có thể thử nghiệm container của mình cục bộ mà không cần phải triển khai lên AWS mỗi lần. Bằng cách sử dụng Lambda Runtime Interface Emulator, bạn có thể chạy và kiểm tra chức năng Lambda ngay trên máy tính cá nhân của mình.
Cách thử nghiệm:
Cài đặt Lambda Runtime Interface Emulator vào container của bạn.
Khởi động container và thử nghiệm bằng cách gửi các sự kiện tương tự như khi Lambda được kích hoạt.
Sau khi thử nghiệm xong, bạn có thể sửa đổi mã nguồn và cài đặt lại các phụ thuộc, sau đó build và thử nghiệm lại.
Điều này giúp bạn tiết kiệm thời gian và chi phí vì không cần triển khai mỗi lần thay đổi nhỏ trong mã nguồn.
5. Kết luận
Lambda Container Images là một tính năng mạnh mẽ mở rộng khả năng của AWS Lambda, cho phép bạn triển khai các chức năng phức tạp với môi trường tùy chỉnh. Điều này rất phù hợp khi bạn cần sử dụng nhiều thư viện hoặc các phần mềm không có sẵn trong môi trường Lambda thông thường.
Chiến lược tối ưu hóa container images cho Lambda
Sử dụng các Base Images do AWS cung cấp:
Lợi ích: Những base image này được xây dựng trên Amazon Linux 2, đã được Lambda service cache sẵn, giúp quá trình tải nhanh hơn và an toàn hơn.
Ví dụ: Nếu bạn phát triển ứng dụng Node.js, bạn có thể sử dụng base image
amazon/aws-lambda-nodejs:12
. Image này đã có sẵn tất cả các công cụ cần thiết cho môi trường Lambda. Bạn chỉ cần tập trung vào việc thêm mã nguồn và các thư viện phụ thuộc của mình mà không cần lo lắng về môi trường nền tảng.
Sử dụng kỹ thuật Multi-Stage Builds (Xây dựng nhiều giai đoạn):
Ý nghĩa: Multi-stage builds là cách tiếp cận trong Docker giúp bạn tạo ra các image nhỏ gọn hơn bằng cách chỉ giữ lại những phần quan trọng cần thiết trong image cuối cùng. Các bước xây dựng trung gian sẽ bị loại bỏ, giúp giảm dung lượng container image.
Ví dụ: Bạn có thể xây dựng ứng dụng của mình trong một stage (giai đoạn), cài đặt tất cả các công cụ cần thiết, sau đó chỉ copy mã đã được biên dịch (compiled code) vào một stage cuối cùng nhẹ hơn. Điều này làm giảm kích thước image.
Xây dựng từ ổn định đến thay đổi thường xuyên (Stable to Frequently Changing):
Ý nghĩa: Để tối ưu quá trình build và triển khai, hãy sắp xếp các phần thay đổi thường xuyên (chẳng hạn như mã nguồn) càng về sau trong Dockerfile càng tốt. Điều này giúp Docker có thể tái sử dụng các layer ổn định trước đó, chỉ phải build lại những phần thay đổi, từ đó tiết kiệm thời gian build.
Ví dụ: Đặt lệnh
COPY
mã nguồn của bạn ở phần dưới của Dockerfile, còn các bước cài đặt thư viện phụ thuộc (có xu hướng ổn định hơn) ở phần trên.
Sử dụng một repository duy nhất cho các hàm có nhiều lớp lớn (Large Layers):
Lợi ích: ECR (Elastic Container Registry) tự động nhận diện và so sánh từng layer của container image. Điều này giúp bạn tránh phải tải lên nhiều lần các layer không thay đổi, giúp quá trình triển khai nhanh hơn và tiết kiệm băng thông.
Ví dụ: Nếu bạn có nhiều hàm Lambda sử dụng chung các thư viện hoặc base image lớn, bạn có thể chỉ cần lưu một lần và tái sử dụng giữa các hàm khác nhau.
Lưu trữ các hàm Lambda lớn (lên đến 10 GB)
Một trong những lợi ích lớn nhất khi sử dụng container image cho Lambda là bạn có thể tải lên các hàm Lambda có dung lượng lên tới 10 GB. Điều này rất hữu ích khi:
Bạn có các thư viện hoặc mô hình machine learning lớn.
Bạn cần triển khai ứng dụng với nhiều file dữ liệu hoặc công cụ cần thiết để xử lý.
Ví dụ thực tế:
- Bạn đang phát triển một ứng dụng xử lý hình ảnh lớn, sử dụng nhiều thư viện đồ hoạ và model AI lớn. Thay vì phải chia nhỏ các thư viện để phù hợp với giới hạn 50MB của Lambda truyền thống, bạn có thể đóng gói tất cả trong một container image và triển khai trực tiếp lên Lambda.
Kết luận
Bằng cách tuân thủ những best practices trên, bạn có thể tối ưu hóa việc sử dụng Lambda Container Images để triển khai các ứng dụng phức tạp, quản lý tốt hơn các thư viện phụ thuộc và giảm thời gian triển khai.
Trong AWS Lambda, các phiên bản đóng vai trò quan trọng trong việc quản lý và duy trì các hàm Lambda. Đặc biệt, khi bạn bắt đầu làm việc với Lambda để thi chứng chỉ AWS Certified Developer – Associate, việc hiểu về cơ chế phiên bản giúp bạn dễ dàng quản lý mã nguồn và cấu hình của hàm Lambda. Sau đây là các giải thích chi tiết, dễ hiểu về nội dung trong ảnh:
1. $LATEST (mutable)
$LATEST là phiên bản mặc định của Lambda khi bạn tạo hoặc chỉnh sửa hàm. Khi bạn thực hiện thay đổi mã hoặc cấu hình hàm Lambda, các thay đổi đó sẽ áp dụng ngay lập tức vào $LATEST.
Mutable (có thể thay đổi): $LATEST không phải là phiên bản cố định. Khi bạn cập nhật hàm, nội dung trong $LATEST cũng sẽ thay đổi theo.
Ví dụ:
- Bạn tạo một hàm Lambda để xử lý dữ liệu đầu vào. Mỗi khi bạn thử nghiệm các thay đổi mới cho hàm này (thêm logic xử lý, thay đổi cấu hình), những thay đổi đó sẽ tự động áp dụng lên $LATEST.
2. Khi sẵn sàng để xuất bản (publish) hàm Lambda, bạn tạo một phiên bản (version)
Sau khi hàm Lambda đã được hoàn thiện và thử nghiệm, bạn có thể "xuất bản" một phiên bản cụ thể. Khi xuất bản, bạn tạo ra một bản sao của mã và cấu hình hiện tại từ $LATEST và tạo thành một phiên bản (ví dụ như V1, V2).
Phiên bản là bất biến (immutable): Khi đã xuất bản, phiên bản đó không thể thay đổi được. Nếu bạn muốn cập nhật mã hoặc cấu hình, bạn phải tạo một phiên bản mới (ví dụ V2).
Ví dụ:
- Giả sử bạn có hàm Lambda tên là
processData
đang trong quá trình thử nghiệm. Khi bạn chắc chắn rằng hàm hoạt động tốt, bạn xuất bản phiên bản V1. Sau đó, nếu bạn tiếp tục cập nhật mã và cần thử nghiệm thêm, bạn có thể tiếp tục làm việc với $LATEST. Khi thay đổi tiếp theo đã sẵn sàng, bạn có thể xuất bản nó thành phiên bản V2.
3. Phiên bản có số phiên bản tăng dần
Mỗi phiên bản Lambda khi được xuất bản sẽ có số hiệu phiên bản tăng dần: V1, V2, V3, v.v...
Khi bạn gọi các phiên bản cụ thể, bạn có thể chỉ định số phiên bản cụ thể đó. Ví dụ, bạn có thể chỉ định gọi hàm ở V1 hoặc V2, tùy thuộc vào yêu cầu của ứng dụng.
Ví dụ:
- Nếu bạn có một ứng dụng có nhiều môi trường (staging, production), môi trường staging có thể sử dụng $LATEST để thử nghiệm, trong khi môi trường production sẽ sử dụng V1 hoặc V2 đã được kiểm định.
4. Phiên bản có ARN riêng (Amazon Resource Name)
Mỗi phiên bản của hàm Lambda có ARN riêng, là một định danh duy nhất trong AWS.
Ví dụ về ARN cho phiên bản:Đây là ARN của hàm
processData
phiên bản V1.ruby Copy code arn:aws:lambda:us-west-2:123456789012:function:processData:1
Ví dụ:
- Khi bạn triển khai các phiên bản khác nhau của cùng một hàm Lambda vào các môi trường khác nhau (staging, production), bạn sẽ sử dụng ARN cụ thể cho từng phiên bản. Ví dụ, môi trường staging có thể sử dụng ARN của $LATEST, còn production có thể sử dụng ARN của V1.
5. Phiên bản là sự kết hợp của mã và cấu hình
- Mỗi phiên bản Lambda không chỉ chứa mã nguồn mà còn lưu giữ toàn bộ cấu hình (timeout, bộ nhớ, biến môi trường, v.v...). Điều này đảm bảo rằng phiên bản đã xuất bản sẽ chạy chính xác như cấu hình đã được định nghĩa tại thời điểm xuất bản, mà không bị ảnh hưởng bởi các thay đổi sau này.
Ví dụ:
- Bạn xuất bản một phiên bản V1 với cấu hình sử dụng 512MB bộ nhớ và thời gian timeout là 3 giây. Sau này, nếu bạn thay đổi cấu hình bộ nhớ thành 1024MB và thời gian timeout thành 6 giây trong $LATEST, phiên bản V1 vẫn giữ nguyên cấu hình ban đầu với 512MB và 3 giây.
6. Các phiên bản có thể được truy cập riêng lẻ
- Bạn có thể gọi các phiên bản cụ thể của Lambda bằng cách chỉ định ARN của phiên bản đó. Điều này đặc biệt hữu ích khi bạn cần thử nghiệm hoặc triển khai những thay đổi mà không làm ảnh hưởng đến phiên bản đang chạy trong môi trường production.
Ví dụ:
- Ứng dụng của bạn có thể sử dụng phiên bản V1 trong môi trường production, trong khi nhóm phát triển vẫn tiếp tục thử nghiệm với $LATEST mà không ảnh hưởng đến các yêu cầu từ production.
Kết luận
Việc quản lý phiên bản trong Lambda giúp đảm bảo mã nguồn và cấu hình được quản lý tốt, cho phép bạn quay lại hoặc triển khai các phiên bản khác nhau của hàm Lambda một cách linh hoạt. Đặc biệt, khi chuẩn bị thi AWS Certified Developer – Associate, bạn cần nắm vững cơ chế phiên bản này để sử dụng trong các bài toán quản lý ứng dụng serverless trên AWS.
Bí danh Lambda trong AWS
Trong AWS Lambda, Aliases (bí danh) là một khái niệm quan trọng giúp bạn quản lý các phiên bản hàm Lambda một cách linh hoạt và dễ dàng. Điều này rất quan trọng khi bạn chuẩn bị cho kỳ thi AWS Certified Developer – Associate vì việc sử dụng bí danh giúp quản lý triển khai (deployment) và thử nghiệm trở nên dễ dàng hơn.
1. Aliases là "con trỏ" trỏ đến các phiên bản Lambda
- Aliases đóng vai trò như "con trỏ" để tham chiếu đến các phiên bản cụ thể của hàm Lambda. Bạn có thể nghĩ về aliases như là một cách đặt tên thân thiện cho các phiên bản của Lambda, giúp dễ dàng quản lý và tham chiếu đến các phiên bản này.
Ví dụ:
- Giả sử bạn có phiên bản V1 và V2 của hàm Lambda. Thay vì sử dụng ARN của các phiên bản này trực tiếp, bạn có thể tạo bí danh như DEV, PROD, TEST để trỏ đến các phiên bản tương ứng. Ví dụ, PROD alias có thể trỏ đến V1 (production), còn DEV alias có thể trỏ đến $LATEST (phiên bản mới nhất cho môi trường phát triển).
2. Có thể định nghĩa các bí danh "dev", "test", "prod" trỏ đến các phiên bản khác nhau của Lambda
Bạn có thể tạo ra nhiều bí danh khác nhau như dev, test, prod để phục vụ cho các mục đích triển khai khác nhau:
DEV alias: Dùng cho phát triển, thử nghiệm.
TEST alias: Dùng cho môi trường kiểm thử.
PROD alias: Dùng cho môi trường sản xuất (production).
Ví dụ:
- Môi trường DEV alias có thể trỏ đến $LATEST để thử nghiệm mã mới, còn PROD alias có thể trỏ đến phiên bản ổn định như V1 hoặc V2 trong môi trường sản xuất.
3. Aliases là mutable (có thể thay đổi)
- Bí danh có thể thay đổi được. Điều này có nghĩa là bạn có thể dễ dàng cập nhật alias để trỏ đến phiên bản khác nhau mà không cần phải thay đổi mã nguồn hay cấu hình tại nơi sử dụng bí danh.
Ví dụ:
- Ban đầu, PROD alias trỏ đến V1. Sau khi kiểm thử thành công phiên bản mới V2, bạn có thể dễ dàng thay đổi PROD alias để trỏ đến V2 mà không cần thay đổi các hệ thống đang sử dụng PROD alias.
4. Aliases hỗ trợ Canary Deployment bằng cách gán trọng số (weight) cho các hàm Lambda
- Canary Deployment cho phép bạn triển khai một phiên bản mới của hàm Lambda nhưng chỉ phục vụ một phần nhỏ lưu lượng (ví dụ 5%) trong khi phiên bản cũ vẫn phục vụ phần lớn lưu lượng. Sau đó, nếu phiên bản mới hoạt động tốt, bạn có thể tăng dần tỷ lệ (weight) của phiên bản mới.
Ví dụ:
- Trong sơ đồ ở ảnh, PROD alias có thể trỏ đến V1 với 95% lưu lượng và V2 với 5% lưu lượng. Nếu V2 hoạt động tốt, bạn có thể dần dần tăng trọng số cho V2 lên 100% và giảm V1 về 0%.
5. Aliases giúp cấu hình sự kiện và điểm đến ổn định
- Khi bạn sử dụng alias, bạn có thể đảm bảo rằng các sự kiện (event triggers) và điểm đến (destinations) sẽ luôn sử dụng phiên bản đúng của hàm Lambda, ngay cả khi bạn thay đổi các phiên bản ở phía sau.
Ví dụ:
- Nếu bạn có SNS Topic hoặc SQS Queue đang gọi hàm Lambda, việc sử dụng alias như PROD đảm bảo rằng các dịch vụ này sẽ luôn trỏ đến phiên bản phù hợp của hàm Lambda mà không cần phải thay đổi ARN mỗi khi bạn xuất bản phiên bản mới.
6. Aliases có ARN riêng
- Tương tự như các phiên bản Lambda, alias cũng có ARN riêng. Điều này giúp bạn dễ dàng tham chiếu đến bí danh mà không cần phải nhớ hay thay đổi ARN của phiên bản cụ thể.
Ví dụ:
ARN của PROD alias có thể trông như sau:
ruby Copy code arn:aws:lambda:us-west-2:123456789012:function:myFunction:PROD
7. Aliases không thể tham chiếu đến alias khác
- Một điểm lưu ý là alias không thể tham chiếu đến alias khác. Nghĩa là bạn không thể tạo một alias trỏ đến một alias khác. Điều này giúp tránh các trường hợp alias bị phụ thuộc lẫn nhau, gây khó khăn trong việc quản lý.
Ví dụ minh họa tổng thể:
Bạn có một hàm Lambda tên là
processOrder
dùng để xử lý đơn hàng. Bạn có hai phiên bản:V1: Phiên bản ổn định cho production.
$LATEST: Phiên bản đang được phát triển.
Bạn tạo alias như sau:
DEV alias trỏ đến $LATEST để các developer thử nghiệm mã mới.
PROD alias trỏ đến V1 để người dùng thực tế gọi phiên bản ổn định.
Khi bạn sẵn sàng triển khai phiên bản mới, bạn tạo phiên bản V2 và sau đó thực hiện Canary Deployment:
- Bạn cập nhật PROD alias để 95% lưu lượng vẫn sử dụng V1, trong khi 5% lưu lượng thử nghiệm V2.
Nếu V2 hoạt động ổn định, bạn cập nhật PROD alias để trỏ toàn bộ lưu lượng sang V2.
Kết luận:
AWS Lambda Aliases là công cụ mạnh mẽ giúp bạn quản lý các phiên bản Lambda một cách dễ dàng và linh hoạt, đồng thời hỗ trợ triển khai canary để giảm thiểu rủi ro khi cập nhật hàm. Việc sử dụng alias giúp tối ưu hóa quy trình phát triển và triển khai, giúp bạn đạt được sự kiểm soát chặt chẽ trong môi trường serverless.
1. CodeDeploy và Quản lý Lưu lượng cho Lambda Aliases
Giải thích:
Amazon CodeDeploy giúp bạn tự động hóa việc chuyển hướng lưu lượng (traffic) giữa các phiên bản của Lambda Function thông qua các Aliases. Một Alias trong Lambda là một "con trỏ" đến một phiên bản cụ thể của Lambda Function. Điều này giúp bạn kiểm soát việc triển khai các phiên bản mới của Lambda Function một cách an toàn và có kiểm soát.
Ví dụ:
Giả sử bạn có một Lambda Function đang hoạt động với phiên bản V1 và bây giờ bạn muốn cập nhật lên V2. Bạn có thể tạo ra một alias có tên là Prod và trỏ alias này đến phiên bản V1. Khi bạn triển khai phiên bản mới (V2), thay vì cập nhật trực tiếp, bạn có thể sử dụng CodeDeploy để dần dần chuyển đổi lưu lượng từ V1 sang V2 một cách từ từ hoặc ngay lập tức dựa trên các chiến lược triển khai khác nhau.
2. Các chiến lược triển khai (Deployment Strategies)
a. Linear (Triển khai tuyến tính):
Triển khai tuyến tính tăng dần lượng lưu lượng đến phiên bản mới qua một khoảng thời gian nhất định. Ví dụ:
- Linear10PercentEvery3Minutes: Cứ mỗi 3 phút, lưu lượng tăng lên thêm 10% đến khi đạt 100%.
Ví dụ:
Bạn đang sử dụng V1 và muốn chuyển dần sang V2. Với chiến lược Linear10PercentEvery10Minutes, CodeDeploy sẽ chuyển 10% lưu lượng sang V2 sau mỗi 10 phút, và sau 100 phút, tất cả lưu lượng sẽ chuyển hoàn toàn sang V2.
b. Canary (Triển khai kiểu Canary):
Với phương pháp này, một tỷ lệ nhỏ lưu lượng được chuyển đến phiên bản mới để kiểm tra, sau đó nếu mọi thứ ổn định, tất cả lưu lượng sẽ được chuyển tiếp theo.
- Canary10Percent30Minutes: Chuyển 10% lưu lượng sang phiên bản mới và sau 30 phút nếu mọi thứ ổn, chuyển toàn bộ lưu lượng còn lại.
Ví dụ:
Bạn muốn thử nghiệm phiên bản mới của Lambda (V2) nhưng chỉ muốn chuyển một phần nhỏ lưu lượng lúc đầu. Với Canary10Percent5Minutes, hệ thống sẽ chuyển 10% lưu lượng trong 5 phút đầu và sau đó chuyển toàn bộ nếu không có lỗi.
c. AllAtOnce (Tất cả ngay lập tức):
- Triển khai ngay lập tức 100% lưu lượng đến phiên bản mới.
Ví dụ:
Nếu bạn đã thử nghiệm kỹ và tự tin rằng phiên bản mới (V2) hoạt động tốt, bạn có thể sử dụng AllAtOnce để ngay lập tức chuyển toàn bộ lưu lượng từ V1 sang V2.
3. Pre và Post Traffic Hooks
Pre-Traffic Hook: Được gọi trước khi lưu lượng được chuyển đến phiên bản mới. Bạn có thể thực hiện các kiểm tra trước khi chuyển đổi lưu lượng.
Post-Traffic Hook: Được gọi sau khi lưu lượng đã được chuyển đến phiên bản mới để đảm bảo chức năng hoạt động ổn định.
Ví dụ:
Giả sử bạn triển khai một phiên bản Lambda mới và muốn chắc chắn rằng tất cả các kết nối đến cơ sở dữ liệu đều hoạt động tốt trước khi chuyển lưu lượng đến. Bạn có thể sử dụng Pre-Traffic Hook để thực hiện kiểm tra kết nối trước khi tiếp nhận bất kỳ lưu lượng nào.
4. AppSpec.yml và Cấu hình triển khai
Giải thích:
AppSpec.yml là tệp cấu hình xác định cách triển khai Lambda Function của bạn với CodeDeploy. Trong tệp này, bạn cần chỉ định:
Name: Tên của Lambda Function cần triển khai.
Alias: Tên alias mà bạn muốn sử dụng cho chức năng Lambda (ví dụ: "Prod" hoặc "Dev").
CurrentVersion: Phiên bản hiện tại mà alias đang trỏ đến.
TargetVersion: Phiên bản mới mà bạn muốn chuyển lưu lượng đến.
Ví dụ:
Nếu Lambda hiện tại đang sử dụng V1 và bạn muốn chuyển sang V2, tệp cấu hình có thể trông như thế này:
yaml
Copy code
version: 0.0
Resources:
- myLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: myLambdaFunction
Alias: myLambdaFunctionAlias
CurrentVersion: 1
TargetVersion: 2
Với cấu hình này, CodeDeploy sẽ chuyển lưu lượng từ V1 sang V2 theo chiến lược triển khai mà bạn chọn.
Kết luận:
Việc sử dụng CodeDeploy để triển khai Lambda giúp bạn triển khai phiên bản mới một cách an toàn và có kiểm soát. Các chiến lược như Canary và Linear rất hữu ích khi bạn muốn triển khai một cách từ từ và an toàn, trong khi AllAtOnce thích hợp khi bạn đã chắc chắn về tính ổn định của phiên bản mới.
Lambda – Function URL
Endpoint HTTP(S) chuyên dụng cho Lambda Function:
AWS Lambda có khả năng cung cấp một endpoint HTTP(S) chuyên dụng cho Lambda Function của bạn. Điều này có nghĩa là bạn có thể gọi hàm Lambda trực tiếp từ trình duyệt web, sử dụng công cụ như curl, Postman, hoặc bất kỳ HTTP client nào khác.
Endpoint này là duy nhất cho mỗi Lambda Function và sẽ không bao giờ thay đổi.
Ví dụ:
Giả sử bạn có một hàm Lambda để xử lý yêu cầu API, Lambda sẽ tạo ra một URL tương tự như sau:
vbnet
Copy code
<https://abc123.lambda-url.us-east-1.on.aws>
Bạn có thể gọi Lambda Function từ trình duyệt như sau:
vbnet
Copy code
<https://abc123.lambda-url.us-east-1.on.aws?name=John>
Lambda Function sẽ xử lý yêu cầu và trả về kết quả ngay trong trình duyệt.
Tạo URL Endpoint cố định:
Một URL Endpoint duy nhất sẽ được tạo cho bạn và nó không bao giờ thay đổi, bất kể bạn có cập nhật hay thay đổi code của Lambda.
Cấu trúc URL endpoint thường như sau:
php Copy code https://<url-id>.lambda-url.<region>.on.aws
Hỗ trợ cả hai phiên bản IP (IPv4 & IPv6).
Sử dụng qua các công cụ HTTP:
- Bạn có thể gọi Lambda Function thông qua các công cụ như curl, Postman hoặc bất kỳ HTTP client nào.
Ví dụ:
Nếu bạn muốn thử nghiệm hàm Lambda của mình từ terminal (dòng lệnh), bạn có thể dùng curl để gửi một yêu cầu như sau:
arduino
Copy code
curl <https://abc123.lambda-url.us-east-1.on.aws>
Chỉ truy cập thông qua Internet công cộng:
- Bạn chỉ có thể truy cập Lambda Function thông qua Internet công cộng, có nghĩa là bạn không thể sử dụng các công nghệ mạng riêng như PrivateLink để gọi Lambda Function qua URL này.
Giải thích thêm:
PrivateLink là một công nghệ của AWS cho phép bạn kết nối các dịch vụ của AWS một cách bảo mật mà không cần qua Internet công cộng. Tuy nhiên, với Lambda Function URL, bạn không thể sử dụng PrivateLink.
Hỗ trợ Resource-based Policies và cấu hình CORS:
- Lambda Function URL hỗ trợ các chính sách dựa trên tài nguyên (Resource-based Policies) và cấu hình CORS (Cross-Origin Resource Sharing).
Ví dụ:
Nếu bạn xây dựng một API mà người dùng có thể truy cập từ các trang web khác nhau, bạn cần cấu hình CORS để cho phép hoặc từ chối các miền (domain) khác gọi đến API của bạn.
Áp dụng được cho các Lambda Alias hoặc phiên bản
$LATEST
:- Bạn có thể tạo Lambda URL cho các alias (như "dev", "prod") hoặc phiên bản
$LATEST
. Tuy nhiên, bạn không thể tạo URL cho các phiên bản cụ thể khác ngoài$LATEST
.
- Bạn có thể tạo Lambda URL cho các alias (như "dev", "prod") hoặc phiên bản
Giải thích thêm:
Khi bạn phát triển ứng dụng trên Lambda, bạn có thể có nhiều phiên bản khác nhau cho cùng một Lambda Function. Phiên bản $LATEST
là phiên bản hiện tại nhất, còn các alias như "prod", "dev" sẽ trỏ tới các phiên bản khác nhau tùy theo môi trường triển khai.
Tạo và cấu hình bằng AWS Console hoặc AWS API:
- Bạn có thể tạo và quản lý Lambda Function URL bằng AWS Console hoặc thông qua AWS API.
Ví dụ:
Trong AWS Console, bạn có thể dễ dàng tạo Lambda Function URL chỉ bằng vài cú nhấp chuột. Hoặc nếu bạn sử dụng AWS CLI, bạn có thể chạy lệnh sau để tạo Lambda Function URL:
bash
Copy code
aws lambda create-function-url-config \\
--function-name my-function \\
--auth-type NONE
Điều chỉnh bằng cách sử dụng Reserved Concurrency (Đồng thời):
- Bạn có thể kiểm soát việc đồng thời gọi Lambda (Concurrency) để tránh bị quá tải bằng cách cấu hình Reserved Concurrency.
Giải thích:
Reserved Concurrency cho phép bạn giới hạn số lượng phiên bản Lambda có thể chạy đồng thời để đảm bảo tài nguyên hệ thống không bị quá tải hoặc để điều chỉnh chi phí.
Ví dụ minh họa:
Tạo Lambda Function với URL:
Bước 1: Truy cập AWS Console → Lambda → Create Function.
Bước 2: Sau khi tạo xong, vào mục Function URL và nhấp vào Create URL.
Bước 3: Cấu hình chính sách bảo mật và lấy URL được cung cấp.
Bước 4: Gửi yêu cầu từ trình duyệt hoặc công cụ như Postman để kiểm tra.
Cấu hình CORS:
- Nếu bạn muốn chỉ cho phép các miền cụ thể truy cập Lambda Function, bạn có thể thêm các cấu hình CORS để giới hạn các miền được phép gọi đến URL này.
Giới hạn Concurrency:
- Giả sử bạn muốn giới hạn hàm Lambda chỉ chạy đồng thời tối đa 10 phiên bản để tránh quá tải, bạn có thể cấu hình Reserved Concurrency trong mục Concurrency Settings của Lambda Function.
Kết luận:
Lambda Function URL là một tính năng mạnh mẽ giúp bạn dễ dàng tạo ra các API hoặc xử lý các yêu cầu HTTP mà không cần thiết lập các dịch vụ phức tạp như API Gateway. Đây là một tính năng cực kỳ hữu ích khi bạn muốn thử nghiệm nhanh hoặc triển khai các ứng dụng serverless nhỏ với ít cấu hình.
Lambda – Function URL Security
Resource-based Policy (Chính sách dựa trên tài nguyên):
Resource-based Policy là một loại chính sách bạn có thể áp dụng trực tiếp vào Lambda Function URL để kiểm soát ai có thể truy cập. Bạn có thể cho phép hoặc từ chối truy cập từ:
Các tài khoản AWS khác (authorize other accounts).
CIDR block cụ thể (một dải địa chỉ IP).
IAM principals (người dùng, vai trò, nhóm IAM cụ thể).
Ví dụ cụ thể:
Bạn muốn chỉ cho phép một tài khoản AWS khác (ví dụ tài khoản A) truy cập vào Lambda Function của bạn. Trong trường hợp này, bạn sẽ viết một chính sách (policy) dựa trên tài nguyên như sau:
json Copy code { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "lambda:InvokeFunctionUrl", "Resource": "arn:aws:lambda:us-east-1:987654321098:function:my-function" } ] }
Trong ví dụ trên, chỉ có tài khoản AWS với ID
123456789012
mới có thể gọi Lambda Function của bạn.
Cross-Origin Resource Sharing (CORS - Chia sẻ tài nguyên giữa các miền):
CORS là một tính năng bảo mật của các trình duyệt web, cho phép hoặc từ chối các yêu cầu HTTP từ các miền khác nhau. Điều này rất quan trọng khi bạn muốn cho phép một ứng dụng từ miền khác (domain) gọi đến Lambda Function URL của bạn.
Nếu một ứng dụng ở domain A gọi một API (được triển khai bằng Lambda Function URL) ở domain B, trình duyệt sẽ yêu cầu server ở domain B phải cho phép điều này qua cấu hình CORS.
Ví dụ cụ thể:
- Bạn có một website chạy trên miền example.com và một API được cung cấp bởi Lambda chạy trên miền api.example.com. Khi người dùng truy cập example.com, và trang web cần gọi API từ api.example.com, bạn cần cấu hình CORS cho Lambda Function để cho phép miền example.com gọi đến.
Cách cấu hình CORS cho Lambda Function URL:
Trong AWS Console, khi tạo Lambda Function URL, bạn có thể bật CORS và cấu hình các miền nào được phép gọi API.
Ví dụ, bạn chỉ cho phép yêu cầu từ example.com:
json Copy code { "AllowOrigins": ["<https://example.com>"], "AllowMethods": ["GET", "POST"], "AllowHeaders": ["Content-Type"] }
Minh họa:
Trong sơ đồ minh họa, người dùng truy cập vào trang web tĩnh (static website) được lưu trữ trên S3 Bucket (ví dụ: example.com) và yêu cầu được gửi qua CloudFront đến API chạy trên Lambda Function URL (ví dụ: api.example.com).
Khi API api.example.com thuộc miền khác so với trang web example.com, bạn cần phải cấu hình CORS để cho phép trang web tĩnh gọi API thành công mà không bị trình duyệt chặn.
Tình huống cụ thể:
- Bạn có một ứng dụng React trên S3 để lưu trữ web tĩnh tại example.com. API của bạn chạy trên Lambda với URL là api.example.com. Khi ứng dụng React cần gọi đến API trên Lambda, bạn phải bật CORS để cho phép trang web của bạn (example.com) có quyền truy cập vào API.
Tổng kết:
Resource-based Policy: Cho phép bạn kiểm soát ai có thể truy cập Lambda Function URL dựa trên các tài khoản AWS, CIDR IP hoặc IAM principals.
CORS: Cung cấp tính năng bảo mật để đảm bảo rằng các miền khác chỉ có thể gọi Lambda Function URL khi bạn cho phép.
1. Lambda Function URL
Lambda Function URL là một HTTP(S) endpoint dành riêng cho hàm Lambda của bạn. Điều này có nghĩa là mỗi Lambda có thể được kích hoạt từ bất kỳ HTTP client nào (trình duyệt, Postman, curl
, v.v.) thông qua một URL được AWS tạo ra.
Endpoint không đổi: URL này không thay đổi trong suốt vòng đời của hàm Lambda, và bạn có thể truy cập nó thông qua internet công cộng.
Ví dụ về URL Lambda:
php Copy code https://<url-id>.lambda-url.<region>.on.aws
Không hỗ trợ PrivateLink: Nếu bạn cần bảo mật bằng cách sử dụng VPC, Lambda Function URL không hỗ trợ PrivateLink, nhưng Lambda function thông thường thì có.
CORS và Resource-based Policy: Bạn có thể sử dụng Cross-Origin Resource Sharing (CORS) để kiểm soát việc truy cập từ các domain khác và áp dụng Resource-based Policy để giới hạn quyền truy cập.
Alias & $LATEST: Bạn có thể gán URL cho một alias (ví dụ:
prod
,dev
) hoặc là phiên bản$LATEST
của Lambda, tuy nhiên không thể gán URL cho một phiên bản cụ thể.
2. Lambda Function URL Security
Resource-based Policy: Đây là chính sách cho phép bạn kiểm soát ai được phép gọi hàm Lambda của bạn. Bạn có thể thiết lập tài khoản AWS khác, IAM Principal cụ thể, hoặc các dải địa chỉ CIDR để cho phép truy cập.
Ví dụ về Resource-based Policy:
json Copy code { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "lambda:InvokeFunctionUrl", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function", "Condition": { "StringEquals": { "LambdaFunctionUrlAuthType": "NONE" } } } ] }
CORS (Cross-Origin Resource Sharing): Nếu hàm Lambda của bạn được gọi từ một domain khác với nguồn chính (ví dụ từ
api.example.com
khi hàm Lambda của bạn được host trênexample.com
), bạn cần thiết lập CORS để cho phép giao tiếp giữa các domain khác nhau.
3. AuthType: NONE và AWS_IAM
AuthType: NONE: Với kiểu xác thực này, bạn cho phép bất kỳ ai truy cập hàm Lambda của mình mà không cần xác thực. Để bảo vệ, bạn cần thiết lập Resource-based Policy để kiểm soát quyền truy cập.
Ví dụ về cách hoạt động của AuthType: NONE:
- Tất cả người dùng trên internet đều có thể gọi đến Lambda function nếu hàm Lambda được cấu hình với
AuthType: NONE
.
- Tất cả người dùng trên internet đều có thể gọi đến Lambda function nếu hàm Lambda được cấu hình với
AuthType: AWS_IAM: Xác thực dựa trên AWS IAM cho phép bạn kiểm soát truy cập vào hàm Lambda dựa trên quyền của IAM. Để IAM được phép gọi hàm Lambda, bạn cần thiết lập cả Identity-based Policy (chính sách định danh IAM) và Resource-based Policy.
Same Account: IAM trong cùng một tài khoản có thể truy cập hàm Lambda nếu một trong hai chính sách (Identity-based hoặc Resource-based) cho phép truy cập.
Cross Account: Khi truy cập từ tài khoản khác, cả hai chính sách (Identity-based và Resource-based) đều phải cho phép truy cập.
4. Ví dụ thực tế:
Tạo Lambda Function URL: Bạn có thể tạo một Lambda Function URL cho bất kỳ hàm Lambda nào của mình để phục vụ các API công cộng hoặc để thực hiện các tác vụ nền.
Bảo mật với IAM: Nếu bạn muốn chỉ cho phép các tài khoản AWS cụ thể gọi hàm Lambda của mình, bạn cần thiết lập Resource-based Policy và kiểm tra các điều kiện xác thực.
AWS Lambda và CodeGuru Profiling
1. Tổng quan về AWS Lambda và CodeGuru Profiling
AWS CodeGuru Profiler là một công cụ giúp bạn có cái nhìn sâu sắc về hiệu suất runtime của các hàm Lambda, đặc biệt là với các runtime như Java và Python. Mục tiêu chính là giúp bạn tối ưu hóa hiệu suất và giảm thiểu chi phí vận hành thông qua việc phân tích thời gian xử lý, tài nguyên tiêu thụ, và các "bottleneck" trong mã nguồn.
2. Cách hoạt động của CodeGuru Profiler
Khi bạn kích hoạt CodeGuru Profiler cho một hàm Lambda:
CodeGuru Profiler sẽ tạo ra một Profiler Group cho hàm Lambda của bạn.
Nhóm này sẽ thu thập thông tin chi tiết về hoạt động runtime của hàm Lambda như CPU, thời gian xử lý của các đoạn mã cụ thể, giúp phát hiện những đoạn mã tốn nhiều thời gian hoặc tài nguyên.
3. Các bước kích hoạt CodeGuru Profiler cho Lambda
Bước 1: Truy cập vào AWS Lambda Console và kích hoạt CodeGuru Profiler cho hàm Lambda của bạn.
Ví dụ: Khi kích hoạt, một lớp (layer) CodeGuru Profiler sẽ tự động được thêm vào hàm Lambda của bạn.
Bước 2: Sau khi kích hoạt, Lambda sẽ thêm:
Layer của CodeGuru Profiler vào hàm của bạn.
Environment Variables (biến môi trường) để liên kết hàm Lambda với CodeGuru Profiler.
Chính sách quyền truy cập (Policy):
AmazonCodeGuruProfilerAgentAccess
sẽ được thêm vào hàm Lambda để cấp quyền truy cập cho CodeGuru Profiler.
4. Ví dụ thực tế
Ứng dụng thực tiễn của CodeGuru Profiler: Giả sử bạn có một hàm Lambda xử lý các yêu cầu API và bạn muốn tối ưu hóa hiệu suất. CodeGuru sẽ giúp bạn phát hiện những đoạn mã nào tốn nhiều thời gian xử lý, giúp bạn tập trung tối ưu hóa chúng để giảm thời gian phản hồi và tiết kiệm chi phí.
Ví dụ về runtime Java: Nếu bạn có một ứng dụng Java chạy trên Lambda, CodeGuru có thể phân tích chi tiết các phần như Garbage Collection (GC), việc phân bổ bộ nhớ không hiệu quả, và các đoạn mã làm tăng độ trễ.
5. Lợi ích của việc sử dụng CodeGuru Profiler
Cải thiện hiệu suất: Bạn có thể dễ dàng xác định và tối ưu hóa các phần của mã Lambda gây ra độ trễ hoặc tiêu tốn nhiều tài nguyên.
Tối ưu chi phí: Bằng cách giảm thời gian thực thi và sử dụng tài nguyên, bạn có thể giảm chi phí vận hành Lambda.
Phân tích runtime: Thông qua các biểu đồ và báo cáo, bạn sẽ thấy được chi tiết thời gian xử lý của từng phần mã, giúp đưa ra quyết định tối ưu chính xác.
6. Tính năng hỗ trợ cho Java và Python
Hiện tại, CodeGuru Profiler chỉ hỗ trợ cho các hàm Lambda chạy trên runtime Java và Python, do đó nếu bạn sử dụng các ngôn ngữ khác như Node.js hoặc Go thì sẽ chưa thể áp dụng tính năng này.
7. Kết luận
Việc sử dụng CodeGuru Profiler không chỉ giúp bạn phân tích hiệu suất hàm Lambda một cách sâu sắc mà còn giúp tối ưu hóa tài nguyên và chi phí. Trong kỳ thi AWS Associate Developer Certification, việc hiểu cách sử dụng CodeGuru Profiler sẽ giúp bạn nắm vững kỹ thuật tối ưu hóa hiệu suất và tận dụng tốt các công cụ AWS.
AWS Lambda Limits (Giới hạn của AWS Lambda) - Nội dung trên ảnh
Trong quá trình học và chuẩn bị cho kỳ thi AWS Certified Developer - Associate, một trong những phần quan trọng mà bạn cần hiểu rõ là giới hạn của AWS Lambda. Những giới hạn này áp dụng cho mỗi vùng (region) mà bạn triển khai Lambda và nó ảnh hưởng đến cách bạn tối ưu hóa và thiết kế ứng dụng.
1. Giới hạn liên quan đến quá trình thực thi (Execution Limits)
Memory allocation: Dung lượng bộ nhớ mà Lambda có thể sử dụng dao động từ 128 MB đến 10 GB, được tăng dần theo từng bậc 1 MB.
- Ví dụ: Nếu bạn có một ứng dụng nhỏ và cần ít tài nguyên, bạn có thể đặt bộ nhớ là 256 MB. Nếu ứng dụng cần xử lý lớn hơn, như xử lý video hoặc các tác vụ AI/ML, bạn có thể tăng lên mức tối đa 10 GB.
Maximum execution time: Thời gian thực thi tối đa của Lambda là 900 giây (tương đương với 15 phút). Nếu một hàm Lambda vượt quá thời gian này, nó sẽ bị dừng (timeout).
- Ví dụ: Nếu bạn có một hàm Lambda xử lý dữ liệu lớn, bạn cần đảm bảo rằng nó hoàn thành trong khoảng 15 phút, nếu không cần tìm cách tối ưu hoá hoặc chia nhỏ công việc.
Environment variables: Lambda cho phép bạn sử dụng các biến môi trường, nhưng giới hạn kích thước tổng của các biến môi trường là 4 KB.
- Ví dụ: Bạn có thể lưu trữ thông tin cấu hình như các key API, hoặc thông tin kết nối đến cơ sở dữ liệu, nhưng phải đảm bảo dung lượng không vượt quá giới hạn 4 KB.
Disk capacity (in /tmp): Lambda cung cấp một thư mục tạm thời (
/tmp
) để bạn lưu trữ dữ liệu trong suốt thời gian thực thi. Dung lượng có thể dao động từ 512 MB đến 10 GB.- Ví dụ: Nếu ứng dụng của bạn cần xử lý file tạm thời, như tải xuống một file lớn, bạn có thể lưu trữ nó trong thư mục
/tmp
trước khi xử lý, nhưng cần đảm bảo rằng dung lượng file không vượt quá giới hạn.
- Ví dụ: Nếu ứng dụng của bạn cần xử lý file tạm thời, như tải xuống một file lớn, bạn có thể lưu trữ nó trong thư mục
Concurrency executions: Mặc định, một hàm Lambda có thể thực thi song song lên đến 1000 lần. Nếu cần thêm, bạn có thể yêu cầu AWS tăng giới hạn này.
- Ví dụ: Khi một hàm Lambda được kích hoạt đồng thời từ nhiều sự kiện khác nhau (như từ S3 hoặc API Gateway), số lượng thực thi song song tối đa là 1000. Nếu số lượng yêu cầu cao hơn, các yêu cầu vượt quá sẽ bị "throttle" (nghẽn).
2. Giới hạn liên quan đến quá trình triển khai (Deployment Limits)
Lambda function deployment size (compressed .zip): Khi bạn triển khai một hàm Lambda, file nén
.zip
chứa mã nguồn và các thư viện không được vượt quá 50 MB.- Ví dụ: Nếu bạn có một ứng dụng lớn với nhiều thư viện phụ thuộc, bạn cần kiểm tra và tối ưu hóa kích thước file nén để không vượt quá 50 MB.
Uncompressed deployment size: Sau khi giải nén, tổng dung lượng mã nguồn và các thư viện của Lambda không được vượt quá 250 MB.
- Ví dụ: Đối với các hàm Lambda phức tạp, như tích hợp với nhiều SDK của AWS, bạn cần đảm bảo rằng tổng kích thước của tất cả mã nguồn và thư viện không vượt quá 250 MB.
Sử dụng thư mục /tmp: Như đã nói ở phần trên, bạn có thể sử dụng thư mục
/tmp
để lưu trữ file tạm thời khi Lambda chạy, với dung lượng từ 512 MB đến 10 GB.Size of environment variables: Giới hạn tổng của các biến môi trường là 4 KB.
- Ví dụ: Nếu bạn cần lưu trữ nhiều thông tin cấu hình, bạn có thể cần xem xét cách tổ chức dữ liệu để không vượt quá giới hạn này, chẳng hạn bằng cách sử dụng AWS Secrets Manager hoặc SSM Parameter Store.
AWS Lambda Best Practices (Các thực hành tốt nhất cho AWS Lambda) - Nội dung trên ảnh
Để chuẩn bị cho kỳ thi AWS Certified Developer - Associate, bạn cần nắm vững các thực hành tốt nhất khi làm việc với AWS Lambda. Đây là những kỹ thuật giúp bạn tối ưu hóa hàm Lambda, đảm bảo hiệu suất tốt và tuân thủ các quy tắc về bảo mật cũng như hiệu quả chi phí.
1. Thực hiện các công việc nặng bên ngoài hàm xử lý (function handler)
Kết nối đến cơ sở dữ liệu ngoài hàm xử lý của bạn:
Mỗi lần Lambda được kích hoạt, một hàm xử lý (handler) sẽ thực thi. Tuy nhiên, việc kết nối cơ sở dữ liệu chỉ nên thực hiện một lần trong phần khởi tạo, để tránh việc mỗi lần gọi hàm lại tạo một kết nối mới.
Ví dụ: Nếu bạn sử dụng RDS hoặc DynamoDB, hãy kết nối cơ sở dữ liệu ngoài hàm xử lý để tái sử dụng kết nối giữa các lần gọi hàm.
Khởi tạo AWS SDK ngoài hàm xử lý:
AWS SDK có thể chiếm một khoảng thời gian để khởi tạo. Để tối ưu hóa, nên khởi tạo SDK một lần ở ngoài hàm xử lý và tái sử dụng nó cho các lần gọi tiếp theo.
Ví dụ: Khi bạn muốn tải dữ liệu từ S3, bạn chỉ nên khởi tạo kết nối đến S3 Client một lần.
Tải các thư viện hoặc dữ liệu phụ thuộc ngoài hàm xử lý:
- Nếu Lambda của bạn cần sử dụng nhiều thư viện phụ thuộc hoặc tải dữ liệu lớn, bạn nên tải nó trong quá trình khởi tạo (một lần) thay vì trong hàm xử lý.
2. Sử dụng biến môi trường (environment variables)
Chuỗi kết nối đến cơ sở dữ liệu, tên S3 bucket, v.v. không nên được ghi trực tiếp trong mã nguồn, mà thay vào đó nên sử dụng biến môi trường. Điều này giúp bạn dễ dàng thay đổi cấu hình mà không cần chỉnh sửa mã.
Mật khẩu hoặc các giá trị nhạy cảm có thể được mã hóa bằng KMS (Key Management Service).
- Ví dụ: Bạn có thể lưu trữ các thông tin bí mật như API keys, mật khẩu cơ sở dữ liệu hoặc ID bucket S3 trong biến môi trường và mã hóa chúng để đảm bảo an toàn.
3. Tối thiểu hóa kích thước gói triển khai (deployment package)
Chia nhỏ chức năng nếu cần thiết: Nếu một hàm Lambda quá lớn hoặc phức tạp, bạn có thể chia nhỏ thành nhiều hàm để tối ưu hóa thời gian tải và kích thước triển khai.
- Ví dụ: Thay vì có một hàm Lambda lớn xử lý nhiều tác vụ, bạn có thể tách ra thành các hàm nhỏ hơn, mỗi hàm đảm nhiệm một nhiệm vụ cụ thể.
Sử dụng AWS Lambda Layers: Nếu bạn cần sử dụng các thư viện hoặc dữ liệu chung cho nhiều hàm Lambda, hãy tận dụng Layers để không cần nhúng chúng vào từng gói triển khai.
- Ví dụ: Nếu bạn có nhiều hàm Lambda sử dụng cùng một thư viện requests của Python, thay vì nhúng thư viện này vào từng hàm, bạn có thể tạo một Layer chứa thư viện này.
4. Tránh sử dụng mã đệ quy (recursive code)
Không bao giờ để một hàm Lambda tự gọi chính nó (recursive) vì điều này có thể gây ra vòng lặp vô tận và tiêu tốn rất nhiều tài nguyên.
- Ví dụ: Nếu một hàm Lambda tự gọi lại chính nó khi có lỗi xảy ra, điều này sẽ tạo ra một vòng lặp không dừng và gây lỗi hệ thống.