跳到主要内容

Node.js 与云函数

Node.js 后端可以通过 PostgreSQL 协议直连 CloudBase PostgreSQL,适合复杂 SQL、事务、批处理、后台任务和对外 API。

在 CloudBase 中,常见运行环境包括云函数、云托管和自有 Node.js 服务。生产环境建议使用环境变量管理连接信息,并复用连接池。

安装依赖

npm install pg

如果使用 TypeScript,可以同时安装类型声明。

npm install -D @types/pg

配置环境变量

建议使用环境变量保存连接信息。

PGHOST=your-postgres-host
PGPORT=5432
PGDATABASE=postgres
PGUSER=app_user
PGPASSWORD=your-password

不要把数据库密码提交到代码仓库。云函数和云托管可在控制台配置环境变量。

创建连接池

将连接池放在模块顶层,便于云函数复用运行时实例。

import pg from "pg";

const pool = new pg.Pool({
host: process.env.PGHOST,
port: Number(process.env.PGPORT || 5432),
database: process.env.PGDATABASE,
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
ssl: { rejectUnauthorized: false },
max: Number(process.env.PGPOOL_MAX || 5),
idleTimeoutMillis: 30_000,
});

export async function query(sql, params = []) {
return pool.query(sql, params);
}

云函数示例

import { query } from "./db.js";

export async function main(event) {
const limit = Math.min(Number(event.limit || 20), 100);
const { rows } = await query(
"select id, title, done from public.todos order by created_at desc limit $1",
[limit]
);

return { data: rows };
}

参数必须使用占位符传入,避免 SQL 注入。

事务

需要多步写入保持一致时,使用同一个 client 执行事务。

const client = await pool.connect();

try {
await client.query("begin");
await client.query("insert into public.orders(user_id, status) values($1, $2)", [userId, "pending"]);
await client.query("insert into public.logs(user_id, action) values($1, $2)", [userId, "create_order"]);
await client.query("commit");
} catch (error) {
await client.query("rollback");
throw error;
} finally {
client.release();
}

更多事务概念请参考 事务

连接池建议

serverless 环境可能同时启动多个实例。连接池最大连接数应按“实例数 × 每实例连接数”估算,避免超过数据库连接上限。

建议从较小的 max 开始,例如 3 到 5。若业务并发较高,应结合慢查询优化、队列削峰或连接池代理能力综合处理。

权限边界

服务端直连通常使用数据库账号访问,不会自动携带终端用户身份。若服务端需要执行用户态权限,应在 SQL 中显式传入 user_id,或使用受限账号和数据库策略控制范围。

前端用户直接访问数据库时,应使用 RLS。服务端管理员能力不应暴露给客户端。