引言
Serverless架构通过按需执行和自动扩缩容,让开发者专注于业务逻辑而无需管理基础设施。结合边缘计算技术,可以将计算推向离用户更近的位置,显著降低延迟。
本文将介绍Serverless与边缘计算的核心概念、设计模式和实战案例。
Serverless架构模式
Function as a Service(FaaS)
FaaS是Serverless的核心,以函数为单位执行代码。
// AWS Lambda 函数示例
exports.handler = async (event) => {
const { userId, action } = JSON.parse(event.body);
try {
let result;
switch (action) {
case 'getUser':
result = await userService.getUser(userId);
break;
case 'updateUser':
result = await userService.updateUser(userId, event.body);
break;
default:
return {
statusCode: 400,
body: JSON.stringify({ error: 'Invalid action' })
};
}
return {
statusCode: 200,
body: JSON.stringify(result),
headers: {
'Content-Type': 'application/json'
}
};
} catch (error) {
console.error('Error:', error);
return {
statusCode: 500,
body: JSON.stringify({ error: 'Internal server error' })
};
}
};
事件驱动架构
Serverless函数由事件触发,形成松耦合的系统。
# AWS SAM 模板
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
# API Gateway触发
GetUserFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Events:
GetApi:
Type: Api
Properties:
Path: /users/{userId}
Method: GET
# S3事件触发
ImageProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: processor.handler
Runtime: nodejs18.x
Events:
S3Upload:
Type: S3
Properties:
Bucket: !Ref ImageBucket
Events: s3:ObjectCreated:*
# SQS消息触发
OrderProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: order.handler
Runtime: nodejs18.x
Events:
SQSEvent:
Type: SQS
Properties:
Queue: !GetAtt OrderQueue.Arn
BatchSize: 10
编排与协调
使用Step Functions编排多个Serverless函数。
# AWS Step Functions 工作流
Comment: "订单处理工作流"
StartAt: ValidateOrder
States:
ValidateOrder:
Type: Task
Resource: arn:aws:lambda:region:account:function:validateOrder
Next: CheckInventory
Catch:
- ErrorEquals: ["ValidationError"]
Next: OrderFailed
CheckInventory:
Type: Task
Resource: arn:aws:lambda:region:account:function:checkInventory
Next: HasInventory
Catch:
- ErrorEquals: ["InventoryError"]
Next: OrderFailed
HasInventory:
Type: Choice
Choices:
- Variable: "$.available"
BooleanEquals: true
Next: ProcessPayment
Default: OrderFailed
ProcessPayment:
Type: Task
Resource: arn:aws:lambda:region:account:function:processPayment
Next: ShipOrder
Catch:
- ErrorEquals: ["PaymentError"]
Next: OrderFailed
ShipOrder:
Type: Task
Resource: arn:aws:lambda:region:account:function:shipOrder
Next: OrderSuccess
OrderSuccess:
Type: Succeed
OrderFailed:
Type: Fail
Error: "OrderProcessingFailed"
边缘计算架构
Cloudflare Workers
在全球边缘节点执行代码,延迟极低。
// Cloudflare Worker 示例
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 边缘缓存策略
const cacheKey = new Request(url.toString(), request);
const cache = caches.default;
let response = await cache.match(cacheKey);
if (!response) {
// 从源站获取
response = await fetch(request);
// 缓存响应(仅对GET请求)
if (request.method === 'GET' && response.status === 200) {
const cacheResponse = response.clone();
cacheResponse.headers.set('Cache-Control', 'public, max-age=3600');
await cache.put(cacheKey, cacheResponse);
}
}
// 边缘A/B测试
const variant = getVariant(request);
response = new Response(response.body, response);
response.headers.set('X-Variant', variant);
return response;
}
};
function getVariant(request) {
// 基于用户特征分配测试组
const userId = request.headers.get('CF-Connecting-IP');
const hash = simpleHash(userId);
return hash % 2 === 0 ? 'A' : 'B';
}
function simpleHash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
hash = hash & hash;
}
return Math.abs(hash);
}
边缘数据处理
在边缘节点执行数据过滤和转换,减少回源流量。
// 边缘图像处理
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 解析图像转换参数
const width = url.searchParams.get('w');
const height = url.searchParams.get('h');
const format = url.searchParams.get('format') || 'webp';
// 从源站获取原图
const originUrl = `https://origin.example.com${url.pathname}`;
const response = await fetch(originUrl);
if (!response.ok) {
return response;
}
// 在边缘转换图像
const transformedImage = await env.IMAGE_RESIZER.resize(
await response.arrayBuffer(),
{
width: parseInt(width),
height: parseInt(height),
format: format
}
);
return new Response(transformedImage, {
headers: {
'Content-Type': `image/${format}`,
'Cache-Control': 'public, max-age=31536000'
}
});
}
};
冷启动优化
预热策略
// 定时预热Lambda函数
exports.warmer = async (event) => {
console.log('Warm-up invocation at:', new Date().toISOString());
return { statusCode: 200, body: 'Warmed up' };
};
// CloudWatch Events 规则
// 每5分钟触发一次预热
{
"schedule": "rate(5 minutes)",
"input": {
"type": "warmup"
}
}
包大小优化
// 使用Lambda Layers共享依赖
// layer/nodejs/node_modules/ 包含公共依赖
// 函数代码只包含特定依赖
const { DynamoDB } = require('@aws-sdk/client-dynamodb');
exports.handler = async (event) => {
const client = new DynamoDB({});
// 业务逻辑
};
# SAM模板配置Layer
Resources:
CommonLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: common-dependencies
ContentUri: layers/common/
CompatibleRuntimes:
- nodejs18.x
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Layers:
- !Ref CommonLayer
连接池复用
// 数据库连接池复用
const { Pool } = require('pg');
// 在函数外部创建连接池(跨调用复用)
let pool;
if (!pool) {
pool = new Pool({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000
});
}
exports.handler = async (event) => {
const client = await pool.connect();
try {
const result = await client.query('SELECT * FROM users WHERE id = $1', [event.userId]);
return {
statusCode: 200,
body: JSON.stringify(result.rows[0])
};
} finally {
client.release();
}
};
Knative:Kubernetes上的Serverless
服务定义
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: user-service
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/minScale: "1"
autoscaling.knative.dev/maxScale: "10"
autoscaling.knative.dev/target: "100" # 目标并发数
spec:
containers:
- image: gcr.io/my-project/user-service:latest
ports:
- containerPort: 8080
env:
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-secret
key: host
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
事件触发
# Kafka事件源
apiVersion: sources.knative.dev/v1beta1
kind: KafkaSource
metadata:
name: order-events
spec:
consumerGroup: order-processor
bootstrapServers:
- kafka-broker:9092
topics:
- orders
sink:
ref:
apiVersion: serving.knative.dev/v1
kind: Service
name: order-processor
性能优化策略
异步处理
// 使用队列异步处理耗时任务
exports.handler = async (event) => {
const { orderId, userId } = JSON.parse(event.body);
// 快速响应,将任务放入队列
await sqs.sendMessage({
QueueUrl: process.env.ORDER_QUEUE_URL,
MessageBody: JSON.stringify({ orderId, userId })
}).promise();
return {
statusCode: 202,
body: JSON.stringify({
message: 'Order accepted',
orderId: orderId
})
};
};
// 异步处理函数
exports.processor = async (event) => {
for (const record of event.Records) {
const { orderId, userId } = JSON.parse(record.body);
try {
await processOrder(orderId, userId);
} catch (error) {
// 发送到死信队列
await sqs.sendMessage({
QueueUrl: process.env.DLQ_URL,
MessageBody: record.body
}).promise();
}
}
};
缓存策略
// Redis缓存(使用Upstash等服务)
const redis = require('redis');
let client;
async function getRedisClient() {
if (!client) {
client = redis.createClient({
url: process.env.REDIS_URL
});
await client.connect();
}
return client;
}
exports.handler = async (event) => {
const { productId } = event.pathParameters;
const cacheKey = `product:${productId}`;
const redis = await getRedisClient();
// 尝试从缓存获取
let product = await redis.get(cacheKey);
if (!product) {
// 缓存未命中,查询数据库
product = await db.getProduct(productId);
// 写入缓存(TTL 1小时)
await redis.setEx(cacheKey, 3600, JSON.stringify(product));
} else {
product = JSON.parse(product);
}
return {
statusCode: 200,
body: JSON.stringify(product)
};
};
成本优化
内存与执行时间平衡
// 性能测试脚本
const testConfigurations = [
{ memory: 128, description: '128MB' },
{ memory: 256, description: '256MB' },
{ memory: 512, description: '512MB' },
{ memory: 1024, description: '1GB' }
];
async function benchmark(memorySize) {
const startTime = Date.now();
// 执行Lambda函数
const result = await lambda.invoke({
FunctionName: 'my-function',
Qualifier: `$LATEST`,
Payload: JSON.stringify(testPayload)
}).promise();
const duration = Date.now() - startTime;
const cost = calculateCost(memorySize, result.Payload.Duration);
return {
memorySize,
duration,
cost,
costPerRequest: cost / 1000000 // 每百万请求成本
};
}
批处理优化
// 批量处理SQS消息
exports.handler = async (event) => {
const records = event.Records;
// 批量查询数据库
const userIds = records.map(r => JSON.parse(r.body).userId);
const users = await db.getUsersByIds(userIds);
// 批量处理
const results = await Promise.all(records.map(async (record, index) => {
const user = users[index];
return processUser(user);
}));
// 返回批处理结果
return {
batchItemFailures: results
.map((r, i) => r.success ? null : { itemIdentifier: records[i].messageId })
.filter(Boolean)
};
};
总结
Serverless与边缘计算为构建现代分布式系统提供了强大的工具:
- Serverless:按需执行、自动扩缩容、降低运维成本
- 边缘计算:全球分布、低延迟、减轻源站压力
- 冷启动优化:预热、包优化、连接池复用
- 性能优化:异步处理、缓存、批处理
适合场景:事件驱动任务、API网关、定时任务、边缘处理。不适合:长时间运行的进程、有状态服务、高性能计算。
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。