1. 从 FaaS 到 BaaS:我在 VSCode 里跑通 Serverless 闭环的真实路径
Serverless 这个词听起来玄乎,拆开看其实就两件事:FaaS 负责“算”,BaaS 负责“存和连”。FaaS 是函数即服务,你写一段处理逻辑,平台按请求触发、按毫秒计费;BaaS 是后端即服务,数据库、对象存储、消息队列这些能力直接以云服务形式给你,不用自己装 MySQL、不用自己搭对象存储网关。把这两块拼起来,一个后端服务就能在几乎不碰服务器的情况下跑起来。
这篇面向的是已经在用 VSCode 写代码、想把手上的 Node 项目迁到 Serverless 上的开发者。我会用一个 Express 项目做骨架,串起serverless.yml配置、本地invoke调试、云端deploy部署,再接入对象存储做文件上传,最后把 AI 能力用统一 Key 的方式挂进来。整套流程在 VSCode 里完成,命令可复制,配置可复用。
需要提前说清楚:Serverless 不是“没有服务器”,而是服务器这件事被平台抽象掉了。你依然要关心冷启动、连接池、临时目录写入权限这些细节,只是不用再管负载均衡和弹性伸缩的机器层配置。理解这一点,后面的坑就好踩了。
2. 前置准备:TaoToken 统一 Key 与 VSCode 环境
2.1 为什么要在 Serverless 里接统一 Key
Serverless 函数是无状态的,每次冷启动都是新实例,把 AI 调用的鉴权信息硬编码进函数代码里,既不好轮换,也容易在多人协作时泄露。我的做法是把模型调用统一走一个兼容 OpenAI 协议的中转层,Key 放在环境变量里,函数只认base_url和api_key两个值。这样换模型、换供应商都不用改业务代码。
TaoToken 在这里扮演的就是这个统一入口:它提供 OpenAI 兼容的接口,模型对话、代码补全这类能力都能通过同一个 Key 调用。对 Serverless 场景来说,好处是函数里只需要维护一份配置,冷启动时读环境变量即可,不用为每个模型单独写 SDK 适配。
2.2 拿到 Key 并配置到本地
先去控制台创建 API Key,地址是https://taotoken.net/console。创建完复制出来,别直接写进代码,放到项目根目录的.env里:
# .env TAOTOKEN_API_KEY=sk-你的key TAOTOKEN_BASE_URL=https://taotoken.net/api然后在serverless.yml里通过environment字段注入,或者用 Serverless Framework 的dotenv插件读取。我倾向后者,本地和云端配置一致,减少“本地能跑线上报错”的情况。
2.3 VSCode 侧要装的插件
VSCode 里搜Tencent Serverless Toolkit装上,它能在侧边栏直接看到函数列表、本地调试、查看日志。另外装DotENV插件让.env有语法高亮。Node 环境建议 18 LTS 以上,Serverless Framework 用 npm 全局装:
npm install -g serverless serverless -v版本出来就说明 CLI 就绪。如果你用的是 pnpm,全局装也可以,但注意serverless命令的解析路径别被多个包管理器搞混。
3. 可复制配置:serverless.yml 骨架与 AI 接入片段
3.1 初始化项目
用官方模板起一个 Express 项目,省得手写入口:
serverless init express-starter --name sls-ai-demo cd sls-ai-demo npm install目录结构大致是app.js、serverless.yml、package.json。app.js是 Express 入口,serverless.yml是部署描述文件。
3.2 serverless.yml 完整骨架
下面这份配置我实测可用,包含函数定义、API 网关触发、环境变量注入和依赖排除:
app: sls-ai-demo stage: dev component: express name: express-api inputs: src: src: ./ exclude: - .env - node_modules/** - .git/** region: ap-guangzhou runtime: Nodejs18.15 memorySize: 256 timeout: 10 environment: variables: TAOTOKEN_API_KEY: ${env:TAOTOKEN_API_KEY} TAOTOKEN_BASE_URL: ${env:TAOTOKEN_BASE_URL} apigw: isBase64Encoded: false几个关键点:exclude里排掉node_modules能显著加快上传,云端会按package.json重新装依赖;environment.variables用${env:...}语法从本地环境读取,部署时不会把 Key 写进代码仓库;timeout设 10 秒是因为 AI 调用可能比普通接口慢,太短会直接超时。
3.3 接入 AI 能力的配置片段
在app.js里加一个调用模型的路由,用openai这个 npm 包即可,因为它兼容标准协议:
npm install openai// app.js const OpenAI = require("openai"); const client = new OpenAI({ apiKey: process.env.TAOTOKEN_API_KEY, baseURL: process.env.TAOTOKEN_BASE_URL, }); app.post("/ai/chat", async (req, res) => { try { const { prompt } = req.body; const completion = await client.chat.completions.create({ model: "gpt-4o-mini", messages: [{ role: "user", content: prompt }], }); res.json({ reply: completion.choices[0].message.content }); } catch (err) { console.error("AI 调用失败", err); res.status(500).json({ error: err.message }); } });这里baseURL指向https://taotoken.net/api,Key 从环境变量读。函数本身不关心背后是哪个模型,换模型只改model字段。
3.4 对象存储上传配置
BaaS 部分用对象存储做文件上传。装 SDK:
npm install cos-nodejs-sdk-v5 multer body-parserapp.js里配置内存存储引擎,拿到 buffer 后直接传到对象存储:
const multer = require("multer"); const COS = require("cos-nodejs-sdk-v5"); const upload = multer({ storage: multer.memoryStorage() }); const cos = new COS({ SecretId: process.env.COS_SECRET_ID, SecretKey: process.env.COS_SECRET_KEY, }); app.post("/upload", upload.single("file"), (req, res) => { cos.putObject( { Bucket: "your-bucket-1250000000", Region: "ap-guangzhou", Key: `uploads/${Date.now()}-${req.file.originalname}`, Body: req.file.buffer, }, (err, data) => { if (err) return res.status(500).json({ error: err.message }); res.json({ url: data.Location }); } ); });注意serverless.yml里apigw.isBase64Encoded要设成false,否则二进制文件上传会乱码。这个坑我踩过,排查了半天。
4. 验证请求:本地 invoke 与云端部署
4.1 本地调试
Serverless Framework 支持本地启动,不用每次部署到云端验证:
serverless dev它会起一个本地网关,默认监听 3000 端口。另开终端测 AI 路由:
curl -X POST http://localhost:3000/ai/chat \ -H "Content-Type: application/json" \ -d '{"prompt":"用一句话解释什么是 FaaS"}'返回类似{"reply":"FaaS 是把函数作为部署单元..."}就说明本地链路通了。如果报401,检查.env里的 Key 有没有被正确加载;报ECONNREFUSED一般是baseURL写错或网络不通。
4.2 云端部署
本地验证通过后部署:
serverless deploy输出里会给出 API 网关地址,形如https://service-xxxx.gz.apigw.tencentcs.com/release/。用这个地址再测一次:
curl -X POST https://service-xxxx.gz.apigw.tencentcs.com/release/ai/chat \ -H "Content-Type: application/json" \ -d '{"prompt":"Serverless 的冷启动是什么"}'云端返回正常,说明环境变量注入、依赖安装、网关转发都对了。如果云端报Cannot find module 'openai',多半是exclude把node_modules排掉后云端没装依赖,检查package.json里dependencies是否完整。
4.3 查看日志
VSCode 里用 Tencent Serverless Toolkit 插件可以直接看函数日志,或者命令行:
serverless logs -f app日志里能看到console.error输出的错误堆栈,排查 AI 调用超时、对象存储鉴权失败这类问题很直接。
5. 本篇常见错排查
5.1 冷启动导致首次请求超时
函数第一次被调用时要初始化运行环境,如果timeout设得太短,首次请求容易失败。把timeout调到 10 秒以上,或者在函数入口做轻量预热。另外 AI 调用本身耗时较长,别把timeout卡在 3 秒。
5.2 临时目录写入权限
Serverless 运行环境只有/tmp可写,如果你用fs.writeFileSync往项目目录写日志或缓存,会报EACCES。日志目录统一指向/tmp:
const logDir = "/tmp/logs";5.3 环境变量没生效
serverless.yml里用${env:TAOTOKEN_API_KEY}读取的是部署机器上的环境变量,不是.env文件。本地调试时 Serverless Framework 会自动读.env,但云端部署前要确保 CI 或本地 shell 里已经export了这些变量。用serverless deploy --verbose能看到实际注入的值。
5.4 对象存储上传返回 403
检查SecretId和SecretKey是否有该存储桶的写权限,以及Bucket名称是否带上了 APPID 后缀。另外Region要和存储桶所在地域一致,跨地域访问会失败。
5.5 AI 接口返回 404
baseURL末尾不要带/v1,SDK 会自己拼路径。如果写成https://taotoken.net/api/v1,实际请求会变成/api/v1/v1/chat/completions,直接 404。正确写法是https://taotoken.net/api。
6. 把 Key 和文档放在手边,继续往下走
整套流程跑下来,核心就三块:serverless.yml描述资源、函数代码处理逻辑、环境变量隔离敏感信息。FaaS 负责请求触发和弹性伸缩,BaaS 负责存储和外部能力,两者通过函数里的 SDK 调用串起来。
如果你在接入 AI 能力时遇到鉴权或模型选择的问题,可以直接去模型对话页面试一下请求格式,确认 Key 和baseURL没问题再写进函数。长期做编码类 Agent 的话,Coding Plan 那边有更完整的配额和模型组合,适合把 AI 调用从单次请求升级成持续工作流。API Key 的管理和接入文档在控制台和文档页都能找到,配置片段可以直接复制到serverless.yml里用。
下一步可以试试把函数拆成多个路由,用 API 网关做路径映射,再把对象存储的静态网站托管打开,前端和后端就都在 Serverless 上了。