feat: translate batch 3 & 4 (10 more skills: agent-*, ai-*, api-*, aws, azure)
This commit is contained in:
241
docs/vietnamese/skills/aws-serverless/SKILL.vi.md
Normal file
241
docs/vietnamese/skills/aws-serverless/SKILL.vi.md
Normal file
@@ -0,0 +1,241 @@
|
||||
---
|
||||
name: aws-serverless
|
||||
description: "Kỹ năng chuyên biệt để xây dựng các ứng dụng serverless sẵn sàng cho production trên AWS. Bao gồm Lambda functions, API Gateway, DynamoDB, các mẫu hướng sự kiện SQS/SNS, triển khai SAM/CDK, và tối ưu hóa cold start."
|
||||
source: vibeship-spawner-skills (Apache 2.0)
|
||||
---
|
||||
|
||||
# AWS Serverless
|
||||
|
||||
## Các Mẫu (Patterns)
|
||||
|
||||
### Mẫu Lambda Handler
|
||||
|
||||
Cấu trúc Lambda function đúng chuẩn với xử lý lỗi.
|
||||
|
||||
**Khi nào dùng**: ['Bất kỳ triển khai Lambda function nào', 'API handlers, bộ xử lý sự kiện, tác vụ định kỳ']
|
||||
|
||||
```javascript
|
||||
// Node.js Lambda Handler
|
||||
// handler.js
|
||||
|
||||
// Khởi tạo bên ngoài handler (tái sử dụng qua các lần gọi)
|
||||
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
|
||||
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
|
||||
|
||||
const client = new DynamoDBClient({});
|
||||
const docClient = DynamoDBDocumentClient.from(client);
|
||||
|
||||
// Hàm Handler
|
||||
exports.handler = async (event, context) => {
|
||||
// Tùy chọn: Không đợi event loop trống (Node.js) có thể giúp function kết thúc sớm hơn
|
||||
context.callbackWaitsForEmptyEventLoop = false;
|
||||
|
||||
try {
|
||||
// Parse input dựa trên nguồn sự kiện
|
||||
const body = typeof event.body === 'string'
|
||||
? JSON.parse(event.body)
|
||||
: event.body;
|
||||
|
||||
// Logic nghiệp vụ
|
||||
const result = await processRequest(body);
|
||||
|
||||
// Trả về phản hồi tương thích API Gateway
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
body: JSON.stringify(result)
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error:', JSON.stringify({
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
requestId: context.awsRequestId
|
||||
}));
|
||||
|
||||
return {
|
||||
statusCode: error.statusCode || 500,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
error: error.message || 'Internal server error'
|
||||
})
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
async function processRequest(data) {
|
||||
// Logic nghiệp vụ của bạn ở đây
|
||||
const result = await docClient.send(new GetCommand({
|
||||
TableName: process.env.TABLE_NAME,
|
||||
Key: { id: data.id }
|
||||
}));
|
||||
return result.Item;
|
||||
}
|
||||
```
|
||||
|
||||
### Mẫu Tích hợp API Gateway
|
||||
|
||||
Tích hợp REST API và HTTP API với Lambda.
|
||||
|
||||
**Khi nào dùng**: ['Xây dựng REST APIs bằng Lambda', 'Cần các HTTP endpoints cho functions']
|
||||
|
||||
```yaml
|
||||
# template.yaml (SAM)
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
|
||||
Globals:
|
||||
Function:
|
||||
Runtime: nodejs20.x
|
||||
Timeout: 30
|
||||
MemorySize: 256
|
||||
Environment:
|
||||
Variables:
|
||||
TABLE_NAME: !Ref ItemsTable
|
||||
|
||||
Resources:
|
||||
# HTTP API (khuyên dùng cho các trường hợp đơn giản, hiệu năng cao, rẻ hơn)
|
||||
HttpApi:
|
||||
Type: AWS::Serverless::HttpApi
|
||||
Properties:
|
||||
StageName: prod
|
||||
CorsConfiguration:
|
||||
AllowOrigins:
|
||||
- "*"
|
||||
AllowMethods:
|
||||
- GET
|
||||
- POST
|
||||
- DELETE
|
||||
AllowHeaders:
|
||||
- "*"
|
||||
|
||||
# Lambda Functions
|
||||
GetItemFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: src/handlers/get.handler
|
||||
Events:
|
||||
GetItem:
|
||||
Type: HttpApi
|
||||
Properties:
|
||||
ApiId: !Ref HttpApi
|
||||
Path: /items/{id}
|
||||
Method: GET
|
||||
Policies:
|
||||
- DynamoDBReadPolicy:
|
||||
TableName: !Ref ItemsTable
|
||||
|
||||
CreateItemFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: src/handlers/create.handler
|
||||
Events:
|
||||
CreateItem:
|
||||
Type: HttpApi
|
||||
Properties:
|
||||
ApiId: !Ref HttpApi
|
||||
Path: /items
|
||||
Method: POST
|
||||
Policies:
|
||||
- DynamoDBCrudPolicy:
|
||||
TableName: !Ref ItemsTable
|
||||
|
||||
# DynamoDB Table
|
||||
ItemsTable:
|
||||
Type: AWS::DynamoDB::Table
|
||||
Properties:
|
||||
AttributeDefinitions:
|
||||
- AttributeName: id
|
||||
AttributeType: S
|
||||
KeySchema:
|
||||
- AttributeName: id
|
||||
KeyType: HASH
|
||||
BillingMode: PAY_PER_REQUEST
|
||||
|
||||
Outputs:
|
||||
ApiUrl:
|
||||
Value: !Sub "https://${HttpApi}.execute-api.${AWS::Region}.amazonaws.com/prod"
|
||||
```
|
||||
|
||||
### Mẫu SQS Hướng Sự Kiện (Event-Driven SQS Pattern)
|
||||
|
||||
Lambda được kích hoạt bởi SQS để xử lý không đồng bộ tin cậy.
|
||||
|
||||
**Khi nào dùng**: ['Xử lý không đồng bộ, tách biệt (decoupled)', 'Cần logic thử lại và Dead Letter Queue (DLQ)', 'Xử lý tin nhắn theo lô (batches)']
|
||||
|
||||
```yaml
|
||||
# template.yaml
|
||||
Resources:
|
||||
ProcessorFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: src/handlers/processor.handler
|
||||
Events:
|
||||
SQSEvent:
|
||||
Type: SQS
|
||||
Properties:
|
||||
Queue: !GetAtt ProcessingQueue.Arn
|
||||
BatchSize: 10
|
||||
FunctionResponseTypes:
|
||||
- ReportBatchItemFailures # Xử lý thất bại từng phần trong lô
|
||||
```
|
||||
|
||||
```javascript
|
||||
// src/handlers/processor.js
|
||||
exports.handler = async (event) => {
|
||||
const batchItemFailures = [];
|
||||
|
||||
for (const record of event.Records) {
|
||||
try {
|
||||
const body = JSON.parse(record.body);
|
||||
await processMessage(body);
|
||||
} catch (error) {
|
||||
console.error(`Failed to process message ${record.messageId}:`, error);
|
||||
// Báo cáo item này bị lỗi (để SQS thử lại chỉ item này)
|
||||
batchItemFailures.push({
|
||||
itemIdentifier: record.messageId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Trả về các item thất bại để thử lại
|
||||
return { batchItemFailures };
|
||||
};
|
||||
```
|
||||
|
||||
## Anti-Patterns (Nên tránh)
|
||||
|
||||
### ❌ Monolithic Lambda
|
||||
|
||||
**Tại sao tệ**: Gói triển khai lớn gây cold start chậm.
|
||||
Khó mở rộng các hoạt động riêng lẻ.
|
||||
Cập nhật ảnh hưởng đến toàn bộ hệ thống.
|
||||
|
||||
**Thay vào đó**: Chia nhỏ function theo trách nhiệm (Single Reponsibility).
|
||||
|
||||
### ❌ Phụ thuộc Lớn (Large Dependencies)
|
||||
|
||||
**Tại sao tệ**: Tăng kích thước gói triển khai.
|
||||
Làm chậm cold start đáng kể.
|
||||
Hầu hết SDK/thư viện có thể không được sử dụng.
|
||||
|
||||
**Thay vào đó**: Dùng esbuild/webpack để tree-shaking, chỉ import client cần thiết từ AWS SDK v3.
|
||||
|
||||
### ❌ Gọi Đồng bộ trong VPC
|
||||
|
||||
**Tại sao tệ**: Lambdas gắn VPC có overhead thiết lập ENI (dù đã được cải thiện).
|
||||
Tra cứu DNS hoặc kết nối bị chặn làm tồi tệ thêm cold start.
|
||||
|
||||
## ⚠️ Các Cạnh Sắc (Rủi ro)
|
||||
|
||||
| Vấn đề | Mức độ nghiêm trọng | Giải pháp |
|
||||
|-------|----------|----------|
|
||||
| Cold start quá lâu | cao | ## Đo lường pha INIT, sử dụng Provisioned Concurrency nếu cần |
|
||||
| Function bị timeout | cao | ## Đặt timeout phù hợp (mặc định 3s là quá ngắn cho nhiều tác vụ) |
|
||||
| Hết bộ nhớ (OOM) | cao | ## Tăng dung lượng bộ nhớ (cũng tăng CPU) |
|
||||
| Lỗi kết nối mạng trong VPC | trung bình | ## Xác minh cấu hình VPC, Subnet và Security Group |
|
||||
| Connection pool bị cạn kiệt | trung bình | ## Sử dụng `callbackWaitsForEmptyEventLoop = false` và tái sử dụng kết nối |
|
||||
| Lỗi upload file lớn qua API Gateway | trung bình | ## Sử dụng S3 Presigned URLs cho upload trực tiếp |
|
||||
| Đệ quy vô hạn (Infinite Loop) | cao | ## Sử dụng bucket/prefix khác nhau cho trigger S3 |
|
||||
Reference in New Issue
Block a user