脚本性能与内存
脚本是网关里表达力最强、开销也最大的改写手段。本页是脚本性能与内存的唯一权威,其余页面(上游与模型字段、脚本 API 参考、脚本配置、写第一个脚本变换)只留指针指回这里。
开销来自序列化
脚本引擎(基于 QuickJS)拿到的是 JSON body 解析为对象后的形式。开销主要来自 JSON 序列化/反序列化,耗时随 body 大小线性增长。
耗时参考
| body 大小 | 典型单次脚本耗时 |
|---|---|
| < 10 KB | 毫秒级 |
| ~100 KB | 数十毫秒 |
| ~1 MB(多模态大对话,含内联 base64) | 显著上升,且占内存 |
简单改写别用脚本
简单字段增删改用 request_payload 声明式规则——在网关内部直接改写请求体、不经过脚本引擎的序列化,性能最好。选型见 请求改写与路由:怎么选。
反模式:用 after 槽脚本做纯路由决策
大 body 上不要用 after 槽脚本做纯路由决策
after 槽脚本会把整段 body(含内联 base64)读入脚本引擎内存,多模态大对话易触发脚本引擎内存 OOM;且 script_error_mode = log-and-continue 下切路由会被静默跳过。
这类「检测图片/联网 → 切模型」的纯路由决策,只要目标与当前路由同协议,改用原生 switch-route 规则——它的谓词只做结构/小值检查、永不读取二进制内容字节,大请求体的磁盘暂存保持开启,含 base64 的 body 以占位符 + 磁盘临时文件留在磁盘上、不读入内存。
只有切换是跨协议、或判定逻辑超出「字段存在性/小值相等」能表达的范围时,才退回脚本——放 before 槽读客户端原始格式(before 槽在协议翻译前运行,尚未解析为目标协议 body)。
写法建议
- 只读需要读的字段:不要
JSON.stringify(body)整个 body,按需取字段。 - 早返回:条件不满足时尽快
return body,减少不必要的处理。 - 避免在循环里做大对象拷贝。
- 流式响应脚本:对每个块处理,避免累积状态。
出错模式的选择
log-and-continue(默认):脚本失败则原 body 透传,请求不中断。适合非关键改写。log-and-reject:脚本失败直接拒绝请求。合规要求严格(脱敏不能漏)时用这个。
字段见 脚本配置。
常见问题
Q:脚本超时了怎么办?SCRIPT_MAX_OPERATIONS(默认 2000)限制每次脚本执行的最大操作数。超了会被中断。死循环或过重逻辑会被它兜住。
Q:多模态大对话脚本 OOM,但确实需要读图片内容判定? 读图片内容做判定本身就会把 base64 读入内存。考虑把判定改成结构检查(用 switch-route 的 when 谓词检查「有没有 image 块」而非读图片内容),或在上游/模型层用协议覆盖分流。
Q:before 和 after 槽都配了脚本,执行顺序? before 先跑(可触发立即 useModel 切换),after 后跑。一旦 before 触发切换,原路由的 after 不执行。详见 脚本 API 参考。
下一步:请求改写与路由:怎么选 看选型;脚本 API 参考 看 API;脚本配置 看配置。
