Serverless Function 是什么?
Serverless Function(无服务器函数)是一种事件驱动的计算服务,开发者只需要编写业务代码,无需管理服务器基础设施。代码在需要时自动运行,按实际使用量计费。
主要特点
- 按需执行:只在被调用时运行
- 自动扩缩容:根据请求量自动伸缩
- 按使用计费:只为实际执行时间付费
- 无服务器管理:无需关心底层基础设施
- 事件驱动:通过各种事件触发执行
适用场景
1. API 端点和微服务
// Vercel Functions 示例 export default function handler(req, res) { if (req.method === 'POST') { const { email, message } = req.body; // 处理联系表单 await sendEmail(email, message); res.status(200).json({ success: true }); } }
适合:
- RESTful API
- GraphQL 端点
- 轻量级微服务
- 不需要持久连接的服务
2. 数据处理和 ETL
# AWS Lambda 示例 import json import boto3 def lambda_handler(event, context): s3 = boto3.client('s3') # S3 对象创建事件触发 bucket = event['Records'][0]['s3']['bucket']['name'] key = event['Records'][0]['s3']['object']['key'] # 处理上传的文件 if key.endswith('.csv'): process_csv_file(bucket, key) elif key.endswith('.json'): process_json_file(bucket, key) return { 'statusCode': 200, 'body': json.dumps('File processed successfully') }
适合:
- 文件上传后处理
- 数据转换和清洗
- 日志分析
- 批量数据处理
3. 定时任务和 Cron Jobs
// Netlify Functions 示例 exports.handler = async (event, context) => { // 每日数据备份 if (event.httpMethod === 'POST') { try { await backupDatabase(); await sendNotification('Backup completed successfully'); return { statusCode: 200, body: JSON.stringify({ message: 'Backup completed' }) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: error.message }) }; } } };
适合:
- 定时数据同步
- 清理过期数据
- 发送定时通知
- 健康检查
4. 事件响应处理
// Cloudflare Workers 示例 addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const url = new URL(request.url) // 根据不同路径处理不同事件 switch (url.pathname) { case '/webhook/payment': return handlePaymentWebhook(request) case '/webhook/user': return handleUserWebhook(request) default: return new Response('Not found', { status: 404 }) } }
适合:
- Webhook 处理
- 第三方服务集成
- 实时通知
- 事件驱动架构
5. 图像/媒体处理
# AWS Lambda + PIL 示例 import boto3 from PIL import Image import io def lambda_handler(event, context): s3 = boto3.client('s3') bucket = event['bucket'] key = event['key'] # 下载原始图像 response = s3.get_object(Bucket=bucket, Key=key) image = Image.open(io.BytesIO(response['Body'].read())) # 生成多种尺寸的缩略图 sizes = [(150, 150), (300, 300), (800, 600)] for size in sizes: resized = image.resize(size, Image.Resampling.LANCZOS) # 保存到 S3 buffer = io.BytesIO() resized.save(buffer, format='JPEG') thumbnail_key = f"thumbnails/{size[0]}x{size[1]}/{key}" s3.put_object( Bucket=bucket, Key=thumbnail_key, Body=buffer.getvalue(), ContentType='image/jpeg' ) return {'statusCode': 200, 'body': 'Thumbnails generated'}
主流平台使用方式
1. Vercel Functions
// api/hello.js export default function handler(req, res) { const { name = 'World' } = req.query; res.status(200).json({ message: `Hello ${name}!` }); } // api/users/[id].js - 动态路由 export default async function handler(req, res) { const { id } = req.query; const user = await getUserById(id); res.json(user); }
部署:
npm install -g vercel vercel deploy
2. Netlify Functions
// netlify/functions/contact.js exports.handler = async (event, context) => { const { httpMethod, body } = event; if (httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed' }; } const { email, message } = JSON.parse(body); // 发送邮件逻辑 await sendEmail(email, message); return { statusCode: 200, body: JSON.stringify({ success: true }) }; };
配置文件 (
netlify.toml
):[build] functions = "netlify/functions" [[redirects]] from = "/api/*" to = "/.netlify/functions/:splat" status = 200
3. AWS Lambda
// index.js const AWS = require('aws-sdk'); const dynamodb = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event) => { const { httpMethod, pathParameters, body } = event; try { switch (httpMethod) { case 'GET': return await getUser(pathParameters.id); case 'POST': return await createUser(JSON.parse(body)); case 'PUT': return await updateUser(pathParameters.id, JSON.parse(body)); case 'DELETE': return await deleteUser(pathParameters.id); default: return { statusCode: 405, body: JSON.stringify({ message: 'Method not allowed' }) }; } } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: error.message }) }; } };
部署配置 (
serverless.yml
):service: my-api provider: name: aws runtime: nodejs18.x region: us-east-1 functions: api: handler: index.handler events: - http: path: users/{id} method: any cors: true - http: path: users method: post cors: true
4. Cloudflare Workers
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const url = new URL(request.url) // KV 存储操作 if (url.pathname.startsWith('/api/cache/')) { const key = url.pathname.split('/').pop() if (request.method === 'GET') { const value = await MY_KV.get(key) return new Response(value || 'Not found', { status: value ? 200 : 404 }) } if (request.method === 'POST') { const value = await request.text() await MY_KV.put(key, value) return new Response('Stored successfully') } } // 代理请求 if (url.pathname.startsWith('/proxy/')) { const targetUrl = url.pathname.replace('/proxy/', '') return fetch(targetUrl) } return new Response('Hello World!') }
最佳实践场景分析
✅ 适合使用 Serverless 的场景
- 不规律的流量
// 营销活动 API export default async function handler(req, res) { // 可能突然有大量请求,也可能长时间无请求 const campaign = await processCampaignData(req.body); res.json(campaign); }
- 简单的 CRUD 操作
// 博客文章 API export default async function handler(req, res) { switch (req.method) { case 'GET': return res.json(await getPosts()); case 'POST': return res.json(await createPost(req.body)); } }
- 事件驱动的处理
// 文件上传处理 exports.handler = async (event) => { const { bucket, key } = event.Records[0].s3; await processUploadedFile(bucket, key); };
❌ 不适合的场景
- 需要持久连接的应用
// WebSocket 连接 - 不适合 // 长轮询 - 不适合 // 实时聊天 - 建议用传统服务器
- 高计算密集型任务
# 复杂的机器学习训练 - 不适合 # 大数据分析 - 可能超时 # 视频渲染 - 资源限制
- 需要本地状态的应用
// 需要内存缓存的应用 // 需要本地文件系统的应用 // 需要持久化连接池的应用
成本考虑
// 成本优化示例 export default async function handler(req, res) { // 避免冷启动 - 重用连接 if (!global.dbConnection) { global.dbConnection = await createDbConnection(); } // 早期返回减少执行时间 if (!req.body.email) { return res.status(400).json({ error: 'Email required' }); } // 批量处理减少调用次数 const results = await processBatch(req.body.items); res.json(results); }
成本特点:
- 低流量:非常便宜,甚至免费
- 中等流量:通常比传统服务器便宜
- 高流量:可能比传统服务器贵
- 执行时间:按毫秒计费,优化代码很重要
Serverless Functions 特别适合构建现代 Web 应用的 API、处理异步任务、响应事件等场景,是 JAMStack 架构的重要组成部分。