TL;DR
API AWS Lambda cho phép nhà phát triển triển khai, quản lý và gọi các hàm serverless một cách lập trình. Nó sử dụng xác thực IAM, các điểm cuối RESTful để quản lý hàm, các tùy chọn gọi đồng bộ và không đồng bộ, với giới hạn đồng thời ở cấp độ tài khoản. Hướng dẫn này bao gồm thiết lập xác thực, triển khai hàm, các mẫu gọi hàm, ánh xạ nguồn sự kiện và các chiến lược kiến trúc serverless trong môi trường sản xuất.
Giới thiệu
AWS Lambda xử lý hàng nghìn tỷ yêu cầu hàng tháng cho hơn 1 triệu người dùng tích cực. Đối với các nhà phát triển xây dựng ứng dụng serverless, công cụ tự động hóa hoặc kiến trúc hướng sự kiện, tích hợp API Lambda không phải là tùy chọn—mà là thiết yếu cho cơ sở hạ tầng dưới dạng mã (infrastructure as code) và các quy trình CI/CD.
Thực tế là: các nhóm quản lý hơn 50 hàm Lambda theo cách thủ công mất 10-15 giờ mỗi tuần cho việc triển khai, cập nhật cấu hình và giám sát. Một tích hợp API Lambda vững chắc sẽ tự động hóa việc triển khai, thực hiện phát hành blue-green và cho phép mở rộng quy mô động dựa trên nhu cầu.
Hướng dẫn này sẽ dẫn bạn qua toàn bộ quá trình tích hợp API AWS Lambda. Bạn sẽ học về xác thực IAM, tạo và triển khai hàm, các mẫu gọi hàm (đồng bộ/không đồng bộ), ánh xạ nguồn sự kiện, kiến trúc phân lớp và các chiến lược triển khai trong môi trường sản xuất. Đến cuối cùng, bạn sẽ có một tích hợp Lambda sẵn sàng cho sản xuất.
API AWS Lambda là gì?
AWS Lambda cung cấp một API RESTful để quản lý các hàm tính toán serverless. API này xử lý:
- Tạo, cập nhật và xóa hàm
- Triển khai và quản lý phiên bản mã
- Gọi hàm (đồng bộ và không đồng bộ)
- Ánh xạ nguồn sự kiện (SQS, Kinesis, DynamoDB, S3)
- Quản lý lớp (layer) cho mã dùng chung
- Cấu hình biệt danh (alias) và định tuyến
- Quản lý đồng thời và dung lượng dự trữ
- Tích hợp ghi nhật ký và giám sát
Các tính năng chính
| Tính năng | Mô tả |
|---|---|
| API RESTful | Các điểm cuối HTTPS tiêu chuẩn |
| Xác thực IAM | AWS Signature Version 4 |
| Gọi không đồng bộ | Xử lý sự kiện "bắn và quên" (fire-and-forget) |
| Gọi đồng bộ | Mẫu yêu cầu-phản hồi |
| Nguồn sự kiện | Hơn 200 tích hợp dịch vụ AWS |
| Các lớp (Layers) | Mã và các phụ thuộc dùng chung |
| Phiên bản/Biệt danh | Chuyển đổi lưu lượng và hoàn nguyên |
| Đồng thời được cung cấp trước (Provisioned Concurrency) | Loại bỏ khởi động lạnh (cold starts) |
Hỗ trợ Runtime Lambda
| Runtime | Phiên bản | Trường hợp sử dụng |
|---|---|---|
| Node.js | 18.x, 20.x | Backend API, xử lý sự kiện |
| Python | 3.9, 3.10, 3.11 | Xử lý dữ liệu, suy luận ML |
| Java | 11, 17, 21 | Ứng dụng doanh nghiệp |
| Go | 1.x | API hiệu suất cao |
| Rust | 1.x | Hàm có độ trễ thấp |
| .NET | 6, 8 | Workload Windows |
| Ruby | 3.x | Ứng dụng web |
| Tùy chỉnh | Bất kỳ | Runtime dựa trên container |
Tổng quan kiến trúc API
Lambda sử dụng cấu trúc API dịch vụ AWS:
https://lambda.{region}.amazonaws.com/2015-03-31/
Các phiên bản API
| Phiên bản | Trạng thái | Trường hợp sử dụng |
|---|---|---|
| 2015-03-31 | Hiện tại | Tất cả các hoạt động Lambda |
| 2018-01-31 | API Runtime | Giao diện runtime tùy chỉnh |
Bắt đầu: Thiết lập xác thực
Bước 1: Tạo tài khoản AWS và người dùng IAM
Trước khi truy cập API:
- Truy cập Bảng điều khiển AWS
- Tạo tài khoản AWS
- Vào IAM Console > Users > Create User
- Đính kèm các chính sách thực thi Lambda
Bước 2: Tạo thông tin xác thực IAM
Tạo khóa truy cập để truy cập lập trình:
# Phương pháp AWS CLI
aws iam create-access-key --user-name lambda-deployer
# Đầu ra: Lưu trữ an toàn các thông tin này
{
"AccessKey": {
"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}
Lưu ý bảo mật: Lưu trữ thông tin xác thực một cách an toàn:
# ~/.aws/credentials
[lambda-deployer]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# Hoặc sử dụng các biến môi trường
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-east-1"
Bước 3: Hiểu về AWS Signature Version 4
Tất cả các yêu cầu API Lambda đều yêu cầu ký SigV4:
const crypto = require('crypto');
class AWSSigner {
constructor(accessKeyId, secretAccessKey, region, service = 'lambda') {
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.region = region;
this.service = service;
}
sign(request, body = null) {
const now = new Date();
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
const dateStamp = amzDate.slice(0, 8);
// Nhiệm vụ 1: Tạo yêu cầu chuẩn (canonical request)
const hashedPayload = body ? crypto.createHash('sha256').update(body).digest('hex') : 'UNSIGNED-PAYLOAD';
const canonicalUri = request.path;
const canonicalQuerystring = request.query || '';
const canonicalHeaders = `host:${request.host}\nx-amz-date:${amzDate}\n`;
const signedHeaders = 'host;x-amz-date';
const canonicalRequest = `${request.method}\n${canonicalUri}\n${canonicalQuerystring}\n${canonicalHeaders}\n${signedHeaders}\n${hashedPayload}`;
// Nhiệm vụ 2: Tạo chuỗi để ký
const algorithm = 'AWS4-HMAC-SHA256';
const credentialScope = `${dateStamp}/${this.region}/${this.service}/aws4_request`;
const hash = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
const stringToSign = `${algorithm}\n${amzDate}\n${credentialScope}\n${hash}`;
// Nhiệm vụ 3: Tính toán chữ ký
const kDate = this.hmac(`AWS4${this.secretAccessKey}`, dateStamp);
const kRegion = this.hmac(kDate, this.region);
const kService = this.hmac(kRegion, this.service);
const kSigning = this.hmac(kService, 'aws4_request');
const signature = this.hmac(kSigning, stringToSign, 'hex');
// Nhiệm vụ 4: Thêm tiêu đề ủy quyền
const authorizationHeader = `${algorithm} Credential=${this.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
return {
'Authorization': authorizationHeader,
'X-Amz-Date': amzDate,
'X-Amz-Content-Sha256': hashedPayload
};
}
hmac(key, string, encoding = 'buffer') {
return crypto.createHmac('sha256', key).update(string).digest(encoding);
}
}
// Sử dụng
const signer = new AWSSigner(
process.env.AWS_ACCESS_KEY_ID,
process.env.AWS_SECRET_ACCESS_KEY,
'us-east-1'
);
Bước 4: Tạo Client API Lambda
const LAMBDA_BASE_URL = 'https://lambda.us-east-1.amazonaws.com/2015-03-31';
const lambdaRequest = async (path, options = {}) => {
const url = new URL(`${LAMBDA_BASE_URL}${path}`);
const method = options.method || 'GET';
const body = options.body ? JSON.stringify(options.body) : null;
const signer = new AWSSigner(
process.env.AWS_ACCESS_KEY_ID,
process.env.AWS_SECRET_ACCESS_KEY,
'us-east-1'
);
const headers = signer.sign({ method, host: 'lambda.us-east-1.amazonaws.com', path }, body);
const response = await fetch(url.toString(), {
method,
headers: {
'Content-Type': 'application/json',
...headers,
...options.headers
},
body
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Lỗi API Lambda: ${error.Message}`);
}
return response.json();
};
// Sử dụng
const functions = await lambdaRequest('/functions');
console.log(`Tìm thấy ${functions.Functions.length} hàm`);
Thay thế: Sử dụng AWS SDK
Đối với mục đích sử dụng trong môi trường sản xuất, AWS SDK tự động xử lý việc ký:
const { LambdaClient, ListFunctionsCommand, CreateFunctionCommand, InvokeCommand } = require('@aws-sdk/client-lambda');
const lambda = new LambdaClient({ region: 'us-east-1' });
// Liệt kê các hàm
const listCommand = new ListFunctionsCommand({});
const result = await lambda.send(listCommand);
// Tạo hàm
const createCommand = new CreateFunctionCommand({
FunctionName: 'my-function',
Runtime: 'nodejs20.x',
Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
Handler: 'index.handler',
Code: {
S3Bucket: 'my-bucket',
S3Key: 'function.zip'
}
});
const fn = await lambda.send(createCommand);
Quản lý hàm
Tạo một hàm
Tạo hàm Lambda qua API:
const createFunction = async (functionConfig) => {
const response = await lambdaRequest('/functions', {
method: 'POST',
body: {
FunctionName: functionConfig.name,
Runtime: functionConfig.runtime || 'nodejs20.x',
Role: functionConfig.roleArn,
Handler: functionConfig.handler || 'index.handler',
Code: {
S3Bucket: functionConfig.s3Bucket,
S3Key: functionConfig.s3Key
},
Description: functionConfig.description || '',
Timeout: functionConfig.timeout || 3,
MemorySize: functionConfig.memorySize || 128,
Environment: {
Variables: functionConfig.environment || {}
},
Tags: functionConfig.tags || {}
}
});
return response;
};
// Sử dụng
const fn = await createFunction({
name: 'order-processor',
roleArn: 'arn:aws:iam::123456789012:role/lambda-execution-role',
handler: 'index.handler',
runtime: 'nodejs20.x',
s3Bucket: 'my-deployments-bucket',
s3Key: 'order-processor/v1.0.0.zip',
description: 'Xử lý các đơn hàng từ hàng đợi SQS',
timeout: 30,
memorySize: 512,
environment: {
DB_HOST: 'db.example.com',
LOG_LEVEL: 'info'
}
});
console.log(`Hàm đã được tạo: ${fn.FunctionArn}`);
Tải mã trực tiếp
Đối với các hàm nhỏ (dưới 50MB khi đã nén):
const fs = require('fs');
const path = require('path');
const createFunctionWithZip = async (functionName, zipPath) => {
const zipBuffer = fs.readFileSync(zipPath);
const base64Code = zipBuffer.toString('base64');
const response = await lambdaRequest('/functions', {
method: 'POST',
body: {
FunctionName: functionName,
Runtime: 'nodejs20.x',
Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
Handler: 'index.handler',
Code: {
ZipFile: base64Code
}
}
});
return response;
};
// Đóng gói hàm
// zip -r function.zip index.js node_modules/
await createFunctionWithZip('my-function', './function.zip');
Cập nhật mã hàm
Triển khai phiên bản mã mới:
const updateFunctionCode = async (functionName, updateConfig) => {
const response = await lambdaRequest(`/functions/${functionName}/code`, {
method: 'PUT',
body: {
S3Bucket: updateConfig.s3Bucket,
S3Key: updateConfig.s3Key,
Publish: updateConfig.publish || false
}
});
return response;
};
// Sử dụng
const updated = await updateFunctionCode('order-processor', {
s3Bucket: 'my-deployments-bucket',
s3Key: 'order-processor/v1.1.0.zip',
publish: true // Tạo phiên bản mới
});
console.log(`Đã cập nhật lên phiên bản: ${updated.Version}`);
Cập nhật cấu hình hàm
Sửa đổi thời gian chờ, bộ nhớ, môi trường:
const updateFunctionConfig = async (functionName, config) => {
const response = await lambdaRequest(`/functions/${functionName}/configuration`, {
method: 'PUT',
body: {
Runtime: config.runtime,
Handler: config.handler,
Description: config.description,
Timeout: config.timeout,
MemorySize: config.memorySize,
Environment: {
Variables: config.environment
}
}
});
return response;
};
// Sử dụng
const updated = await updateFunctionConfig('order-processor', {
timeout: 60,
memorySize: 1024,
environment: {
DB_HOST: 'new-db.example.com',
LOG_LEVEL: 'debug'
}
});
Xóa một hàm
Xóa hàm:
const deleteFunction = async (functionName, qualifier = null) => {
const path = qualifier
? `/functions/${functionName}?Qualifier=${qualifier}`
: `/functions/${functionName}`;
await lambdaRequest(path, { method: 'DELETE' });
console.log(`Hàm ${functionName} đã bị xóa`);
};
Gọi hàm
Gọi đồng bộ (Yêu cầu-Phản hồi)
Gọi hàm và chờ phản hồi:
const invokeFunction = async (functionName, payload, qualifier = null) => {
const path = qualifier
? `/functions/${functionName}/invocations?Qualifier=${qualifier}`
: `/functions/${functionName}/invocations`;
const response = await lambdaRequest(path, {
method: 'POST',
headers: {
'X-Amz-Invocation-Type': 'RequestResponse', // Đồng bộ
'X-Amz-Log-Type': 'Tail' // Bao gồm nhật ký
},
body: payload
});
// Phân tích phản hồi
const result = JSON.parse(Buffer.from(response.Payload).toString());
const logs = Buffer.from(response.LogResult, 'base64').toString();
return { result, logs };
};
// Sử dụng
const { result, logs } = await invokeFunction('order-processor', {
orderId: 'ORD-12345',
customerId: 'CUST-67890',
items: [
{ sku: 'PROD-001', quantity: 2 },
{ sku: 'PROD-002', quantity: 1 }
]
});
console.log(`Kết quả: ${JSON.stringify(result)}`);
console.log(`Nhật ký:\n${logs}`);
Gọi không đồng bộ (Bắn và quên)
Gọi hàm mà không cần chờ:
const invokeAsync = async (functionName, payload) => {
const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
method: 'POST',
headers: {
'X-Amz-Invocation-Type': 'Event', // Không đồng bộ
'X-Amz-Log-Type': 'None'
},
body: payload
});
return {
statusCode: response.StatusCode,
executionId: response['X-Amz-Execution-Id']
};
};
// Sử dụng - kích hoạt xử lý không đồng bộ
const result = await invokeAsync('email-sender', {
to: 'customer@example.com',
template: 'order-confirmation',
data: { orderId: 'ORD-12345' }
});
console.log(`ID gọi không đồng bộ: ${result.executionId}`);
Gọi thử nghiệm (Dry Run Invocation)
Kiểm tra quyền mà không thực thi:
const dryRunInvocation = async (functionName) => {
const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
method: 'POST',
headers: {
'X-Amz-Invocation-Type': 'DryRun'
}
});
return response;
};
// Sử dụng - xác minh quyền IAM
try {
await dryRunInvocation('order-processor');
console.log('Quyền gọi hàm OK');
} catch (error) {
console.error('Quyền bị từ chối:', error.message);
}
Các loại phản hồi gọi hàm
| Loại gọi hàm | Hành vi | Trường hợp sử dụng |
|---|---|---|
RequestResponse |
Đồng bộ, chờ kết quả | Gọi API, lệnh CLI |
Event |
Không đồng bộ, bắn và quên | Xử lý sự kiện, thông báo |
DryRun |
Chỉ kiểm tra quyền | Xác thực, gỡ lỗi |
Quản lý phiên bản và biệt danh
Xuất bản các phiên bản
Tạo phiên bản hàm bất biến:
const publishVersion = async (functionName, description = null) => {
const response = await lambdaRequest(`/functions/${functionName}/versions`, {
method: 'POST',
body: description ? { Description: description } : {}
});
return response;
};
// Sử dụng
const version = await publishVersion('order-processor', 'v1.2.0 - Thêm tính toán thuế');
console.log(`Phiên bản đã xuất bản: ${version.Version}`);
Tạo biệt danh
Tạo một con trỏ có tên tới phiên bản:
const createAlias = async (functionName, aliasName, version, description = null) => {
const response = await lambdaRequest(`/functions/${functionName}/aliases`, {
method: 'POST',
body: {
Name: aliasName,
FunctionVersion: version,
Description: description
}
});
return response;
};
// Sử dụng - Tạo biệt danh cho sản xuất
const prodAlias = await createAlias('order-processor', 'prod', '5', 'Phiên bản sản xuất');
console.log(`ARN biệt danh: ${prodAlias.AliasArn}`);
Chuyển đổi lưu lượng với cấu hình định tuyến
Dần dần chuyển lưu lượng sang phiên bản mới:
const updateAliasWithRouting = async (functionName, aliasName, routingConfig) => {
const response = await lambdaRequest(`/functions/${functionName}/aliases/${aliasName}`, {
method: 'PUT',
body: {
RoutingConfig: {
AdditionalVersionWeights: routingConfig
}
}
});
return response;
};
// Sử dụng - 10% lưu lượng đến phiên bản 6, 90% đến phiên bản 5
await updateAliasWithRouting('order-processor', 'prod', {
'6': 0.1
});
// Sau khi xác thực, chuyển sang 100%
await updateAliasWithRouting('order-processor', 'prod', {});
Các trường hợp sử dụng biệt danh
| Biệt danh | Phiên bản | Mục đích |
|---|---|---|
dev |
$LATEST | Kiểm thử phát triển |
staging |
Phiên bản đã kiểm thử mới nhất | Xác thực QA |
prod |
Phiên bản ổn định | Lưu lượng sản xuất |
blue |
Sản phẩm hiện tại | Triển khai blue-green |
green |
Phiên bản mới | Triển khai blue-green |
Ánh xạ nguồn sự kiện
Tạo trình kích hoạt SQS
Kết nối hàng đợi SQS với Lambda:
const createSQSEventSource = async (functionName, queueArn, batchSize = 10) => {
const response = await lambdaRequest('/event-source-mappings', {
method: 'POST',
body: {
EventSourceArn: queueArn,
FunctionName: functionName,
BatchSize: batchSize,
Enabled: true
}
});
return response;
};
// Sử dụng
const mapping = await createSQSEventSource(
'order-processor',
'arn:aws:sqs:us-east-1:123456789012:orders-queue',
10
);
console.log(`Nguồn sự kiện đã được tạo: ${mapping.UUID}`);
Tạo trình kích hoạt DynamoDB Stream
Kết nối DynamoDB stream với Lambda:
const createDynamoDBEventSource = async (functionName, streamArn, startingPosition = 'LATEST') => {
const response = await lambdaRequest('/event-source-mappings', {
method: 'POST',
body: {
EventSourceArn: streamArn,
FunctionName: functionName,
StartingPosition: startingPosition,
BatchSize: 100,
BisectBatchOnFunctionError: true,
MaximumRetryAttempts: 3
}
});
return response;
};
// Sử dụng
await createDynamoDBEventSource(
'user-analytics',
'arn:aws:dynamodb:us-east-1:123456789012:table/Users/stream/2026-03-25T00:00:00.000'
);
Các loại nguồn sự kiện
| Nguồn | Trường hợp sử dụng | Hỗ trợ Batch |
|---|---|---|
| SQS | Hàng đợi tin nhắn | Có (1-10) |
| Kinesis | Luồng thời gian thực | Có (1-10.000) |
| DynamoDB Streams | Thay đổi cơ sở dữ liệu | Có (1-1.000) |
| S3 | Sự kiện đối tượng | Không (1 mỗi sự kiện) |
| EventBridge | Định tuyến sự kiện | Có |
| API Gateway | API HTTP | Không |
| Schedule | Công việc định kỳ (Cron jobs) | Không |
Quản lý lớp (Layer)
Tạo một lớp
Đóng gói mã/phụ thuộc dùng chung:
const createLayer = async (layerName, layerConfig) => {
const response = await lambdaRequest('/layers', {
method: 'POST',
body: {
LayerName: layerName,
Description: layerConfig.description,
CompatibleRuntimes: layerConfig.runtimes,
Content: {
S3Bucket: layerConfig.s3Bucket,
S3Key: layerConfig.s3Key
}
}
});
return response;
};
// Sử dụng
const layer = await createLayer('shared-utils', {
description: 'Các tiện ích và phụ thuộc dùng chung',
runtimes: ['nodejs20.x', 'nodejs18.x'],
s3Bucket: 'my-layers-bucket',
s3Key: 'shared-utils/v1.zip'
});
console.log(`ARN của lớp: ${layer.LayerArn}`);
Sử dụng các lớp trong hàm
Đính kèm các lớp vào hàm:
const createFunctionWithLayers = async (functionConfig) => {
const response = await lambdaRequest('/functions', {
method: 'POST',
body: {
FunctionName: functionConfig.name,
Runtime: functionConfig.runtime,
Role: functionConfig.roleArn,
Handler: functionConfig.handler,
Code: {
S3Bucket: functionConfig.s3Bucket,
S3Key: functionConfig.s3Key
},
Layers: functionConfig.layers // Mảng các ARN của lớp
}
});
return response;
};
// Sử dụng
await createFunctionWithLayers({
name: 'api-handler',
roleArn: 'arn:aws:iam::123456789012:role/lambda-execution-role',
handler: 'index.handler',
runtime: 'nodejs20.x',
s3Bucket: 'my-deployments-bucket',
s3Key: 'api-handler/v1.0.0.zip',
layers: [
'arn:aws:lambda:us-east-1:123456789012:layer:shared-utils:1',
'arn:aws:lambda:us-east-1:123456789012:layer:aws-sdk:3'
]
});
Đồng thời và mở rộng quy mô
Thiết lập đồng thời dự trữ (Reserved Concurrency)
Dự trữ dung lượng cho các hàm quan trọng:
const putFunctionConcurrency = async (functionName, reservedConcurrentExecutions) => {
const response = await lambdaRequest(`/functions/${functionName}/concurrency`, {
method: 'PUT',
body: {
ReservedConcurrentExecutions: reservedConcurrentExecutions
}
});
return response;
};
// Sử dụng - Dự trữ 100 lần thực thi đồng thời
await putFunctionConcurrency('order-processor', 100);
Giới hạn đồng thời của tài khoản
| Loại tài khoản | Giới hạn mặc định | Có thể tăng |
|---|---|---|
| Tầng miễn phí (Free Tier) | 1.000 | Có |
| Trả tiền theo mức sử dụng (Pay-as-you-go) | 1.000 | Có |
| Doanh nghiệp (Enterprise) | 1.000+ | Giới hạn tùy chỉnh |
Danh sách kiểm tra triển khai sản xuất
Trước khi triển khai lên môi trường sản xuất:
- [ ] Sử dụng AWS SDK để tự động ký SigV4
- [ ] Triển khai quản lý phiên bản bằng biệt danh
- [ ] Cấu hình đồng thời dự trữ cho các hàm quan trọng
- [ ] Thiết lập hàng đợi thư chết (DLQ) cho các lời gọi không đồng bộ
- [ ] Kích hoạt X-Ray tracing để gỡ lỗi
- [ ] Cấu hình VPC để truy cập cơ sở dữ liệu
- [ ] Thực hiện ghi nhật ký có cấu trúc (định dạng JSON)
- [ ] Thiết lập cảnh báo CloudWatch
- [ ] Sử dụng các lớp (layers) cho các phụ thuộc dùng chung
- [ ] Thực hiện chiến lược triển khai blue-green
Các trường hợp sử dụng thực tế
Backend API
Một công ty SaaS xây dựng API REST serverless:
- Thách thức: Lưu lượng biến động, mở rộng quy mô không thể đoán trước
- Giải pháp: Lambda + API Gateway với tự động mở rộng quy mô
- Kết quả: Thời gian hoạt động 99.99%, giảm 60% chi phí so với EC2
Triển khai chính:
- Các hàm Lambda cho mỗi tài nguyên
- API Gateway để định tuyến/xác thực
- DynamoDB để lưu trữ dữ liệu
- Đồng thời được cung cấp trước (Provisioned concurrency) để có độ trễ nhất quán
Quy trình xử lý sự kiện
Một nền tảng thương mại điện tử xử lý đơn hàng:
- Thách thức: Đơn hàng tăng đột biến trong các sự kiện bán hàng
- Giải pháp: SQS + Lambda với xử lý hàng loạt
- Kết quả: Không mất đơn hàng nào, xử lý tăng đột biến gấp 10 lần
Triển khai chính:
- Hàng đợi SQS đệm đơn hàng
- Lambda xử lý 10 tin nhắn/lô
- DLQ cho các tin nhắn bị lỗi
- Cảnh báo CloudWatch về độ sâu hàng đợi
Kết luận
API AWS Lambda cung cấp các khả năng tính toán serverless toàn diện. Các điểm chính cần ghi nhớ:
- Xác thực IAM với ký SigV4 (sử dụng AWS SDK)
- Các mẫu gọi hàm đồng bộ và không đồng bộ
- Quản lý phiên bản và biệt danh cho việc triển khai
- Ánh xạ nguồn sự kiện cho kiến trúc serverless
- Các lớp (layers) cho mã và các phụ thuộc dùng chung
- Apidog hợp lý hóa việc kiểm thử API và cộng tác nhóm
Phần Câu hỏi thường gặp
Làm cách nào để xác thực với API Lambda?
Sử dụng thông tin xác thực AWS IAM với ký Signature Version 4. AWS SDK tự động xử lý việc ký.
Sự khác biệt giữa gọi đồng bộ và không đồng bộ là gì?
Gọi đồng bộ (RequestResponse) chờ hàm hoàn thành và trả về kết quả. Gọi không đồng bộ (Event) đưa yêu cầu vào hàng đợi và trả về ngay lập tức.
Các phiên bản Lambda hoạt động như thế nào?
Mỗi phiên bản đã xuất bản là một bản chụp bất biến của hàm của bạn. Sử dụng các biệt danh để trỏ đến các phiên bản cụ thể và cho phép chuyển đổi lưu lượng.
Lambda Layers là gì?
Layers đóng gói mã và các phụ thuộc riêng biệt với mã hàm, cho phép chia sẻ thư viện trên nhiều hàm.
Làm cách nào để giảm khởi động lạnh (cold starts)?
Sử dụng đồng thời được cung cấp trước (provisioned concurrency), các gói triển khai nhỏ hơn và các ngôn ngữ biên dịch (Go, Rust) cho các hàm nhạy cảm về độ trễ.
Đồng thời dự trữ (reserved concurrency) là gì?
Đồng thời dự trữ đảm bảo các khe thực thi cho các hàm cụ thể, ngăn chặn các vấn đề "noisy neighbor".
Tôi có thể kích hoạt Lambda từ S3 không?
Có, cấu hình thông báo sự kiện S3 để gọi Lambda khi đối tượng được tạo/xóa.
