Web 函数
Web 函数是云开发提供的新一代云函数运行环境,专门针对 Web 服务场景进行了优化。相比于事件函数,Web 函数支持标准的 HTTP 请求响应模式,用户可以快速将现有的 Web 服务迁移到 Serverless 架构上。
前置条件
- 已开通云开发服务
- 已创建云开发环境
- 本地已安装 CloudBase CLI
运行机制
Web 函数与事件函数的运行机制对比:
特性 | 事件函数 | Web 函数 |
---|---|---|
触发方式 | 事件驱动 | HTTP 请求 |
执行环境 | 每次调用创建新环境 | 支持环境复用 |
连接方式 | 短连接 | 支持长连接 |
端口监听 | 无需监听端口 | 监听 9000 端口 |
适用场景 | 事件处理、定时任务 | Web 服务、API 接口 |
核心特性
Web 函数具备以下核心能力:
- HTTP 请求处理:直接接收和处理标准 HTTP 请求
- SSE 支持:支持 Server-Sent Events 实时推送
- WebSocket 支持:支持 WebSocket 长连接通信
- 文件上传下载:支持文件的上传和下载操作
- 框架兼容:兼容 Express.js、Koa.js 等主流 Web 框架
适用场景
Web 函数特别适用于以下场景:
- RESTful API 服务:构建标准的 REST API 接口
- Web 应用迁移:将现有 Web 应用迁移到 Serverless 架构
- 微服务架构:将单体应用拆分为多个独立的微服务
- 实时通信:基于 SSE 或 WebSocket 的实时数据推送
- 文件处理服务:提供文件上传、下载、转换等功能
开发方式
云开发 Web 函数支持两种开发方式:
1. 框架模式
使用 @cloudbase/functions-framework
框架,保持函数式编程风格:
// 使用函数式写法
exports.main = async function(event, context) {
// 业务逻辑
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello World' })
};
};
2. 原生模式
编写完整的 HTTP 服务代码,监听 9000 端口:
// 使用 Express.js 框架
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({ message: 'Hello World' });
});
app.listen(9000, () => {
console.log('Server running on port 9000');
});
使用 Functions Framework 开发
推荐使用 @cloudbase/functions-framework
框架进行开发,它提供了更简洁的函数式编程体验。
项目结构
my-web-function/
├── scf_bootstrap # 启动脚本(必需)
├── package.json # 项目配置
└── index.js # 函数代码
启动脚本
创建 scf_bootstrap
文件:
#!/bin/bash
node node_modules/@cloudbase/functions-framework/bin/tcb-ff.js --port=9000 --logDirname=/tmp/logs --interceptOutput=false --extendedContextKey=X-Cloudbase-Context
注意
scf_bootstrap
文件需要具有可执行权限,在 Linux/macOS 系统中使用 chmod +x scf_bootstrap
命令设置权限。
依赖配置
package.json
文件:
{
"name": "my-web-function",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@cloudbase/functions-framework": "^1.14.0"
}
}
基础示例
index.js
文件:
exports.main = async function(event, context) {
const { method, path, headers, body } = event;
// 处理不同的 HTTP 方法
switch (method) {
case 'GET':
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: 'Hello from Web Function',
path,
timestamp: new Date().toISOString()
})
};
case 'POST':
return {
statusCode: 201,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: 'Data received',
data: JSON.parse(body || '{}')
})
};
default:
return {
statusCode: 405,
body: JSON.stringify({ error: 'Method not allowed' })
};
}
};
SSE 实时推送示例
Web 函数支持 Server-Sent Events,可以实现实时数据推送:
exports.main = async function(event, context) {
// 切换到 SSE 模式
const sse = context.sse();
// 监听连接关闭事件
sse.on('close', () => {
console.log('SSE connection closed');
});
// 发送实时数据
if (!sse.closed) {
// 发送文本数据
sse.send({ data: 'Hello from SSE function' });
// 发送 JSON 数据
sse.send({
data: JSON.stringify({
type: 'notification',
message: 'New message received',
timestamp: Date.now()
})
});
// 发送 Buffer 数据
sse.send({ data: Buffer.from('Binary data message') });
}
return '';
};
部署配置
使用 CLI 部署
- 安装依赖:
npm install
- 创建
cloudbaserc.json
配置文件:
{
"envId": "your-env-id",
"functions": [
{
"name": "webFunction",
"type": "web",
"source": "./",
"runtime": "Nodejs16.13",
"memorySize": 256,
"timeout": 60,
"environment": {
"NODE_ENV": "production"
}
}
]
}
- 部署函数:
cloudbase functions:deploy webFunction
通过云开发平台部署
- 登录 云开发平台
- 选择目标环境,进入「云函数」页面
- 点击「新建函数」,选择「Web 函数」类型
- 上传代码包或在线编辑代码
- 配置函数参数并部署
函数调用
HTTP API 调用
Web 函数部署成功后,可通过 HTTP API 进行调用:
curl -L 'https://{envId}.api.tcloudbasegateway.com/v1/functions/{functionName}?webfn=true' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-d '{}'
重要提示
调用 Web 函数时必须在 URL 中添加 webfn=true
参数,否则调用会失败。
获取访问令牌
调用 Web 函数需要携带访问令牌,获取方式请参考:Access Token
最佳实践
1. 错误处理
exports.main = async function(event, context) {
try {
// 业务逻辑
const result = await processRequest(event);
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
};
} catch (error) {
console.error('Function error:', error);
return {
statusCode: 500,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
error: 'Internal server error',
message: error.message
})
};
}
};
2. 参数验证
function validateRequest(event) {
const { method, body } = event;
if (method === 'POST') {
const data = JSON.parse(body || '{}');
if (!data.name || !data.email) {
throw new Error('Missing required fields: name, email');
}
// 邮箱格式验证
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
throw new Error('Invalid email format');
}
}
}
3. 环境变量使用
exports.main = async function(event, context) {
const config = {
apiKey: process.env.API_KEY,
dbUrl: process.env.DATABASE_URL,
debug: process.env.NODE_ENV === 'development'
};
if (!config.apiKey) {
return {
statusCode: 500,
body: JSON.stringify({ error: 'Missing API key configuration' })
};
}
// 使用配置进行业务处理
};
注意事项
重要说明
- Web 函数必须监听 9000 端口
- 使用 Functions Framework 时需要包含
scf_bootstrap
启动脚本 - 函数代码包大小限制为 50MB(压缩后)
- 单次请求超时时间最长为 900 秒
- 支持的运行时:Node.js 12.16、14.18、16.13、18.15
与事件函数的差异
Web 函数的 event
和 context
参数与事件函数存在差异:
- event 对象:包含 HTTP 请求的完整信息(method、path、headers、body 等)
- context 对象:提供 SSE 支持等 Web 特有功能
- 环境变量:运行时环境变量可能有所不同
常见问题
如何处理文件上传?
exports.main = async function(event, context) {
const { method, headers, body } = event;
if (method === 'POST' && headers['content-type']?.includes('multipart/form-data')) {
// 处理文件上传逻辑
// 注意:需要解析 multipart 数据
return {
statusCode: 200,
body: JSON.stringify({ message: 'File uploaded successfully' })
};
}
return {
statusCode: 400,
body: JSON.stringify({ error: 'Invalid request' })
};
};
如何实现跨域支持?
exports.main = async function(event, context) {
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
};
// 处理预检请求
if (event.method === 'OPTIONS') {
return {
statusCode: 200,
headers: corsHeaders,
body: ''
};
}
// 正常请求处理
return {
statusCode: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
body: JSON.stringify({ message: 'Success' })
};
};