大模型API计费系统搭建:从配置到扣费验证

给大模型API加计费,核心就两件事:一是在请求转发前校验并预扣额度,二是在响应返回后按实际token用量结算。
比较轻量的做法是用Nginx配合Lua脚本,在网关层拦截请求,用Redis存余额和扣费记录,不需要改动后端模型服务。
下面按从零搭建的顺序讲清楚每一步。

先明确计费链路和准备条件

这套方案适用于自建或代理大模型API、需要按调用量或token数向用户收费的场景。
请求链路是:客户端带API Key请求Nginx,Lua脚本校验Key并预扣额度,放行到后端模型接口,响应返回后Lua读取usage字段完成结算。

需要准备:一台Linux服务器(以Ubuntu 22.04为例)、已安装Nginx、Redis、以及带lua-nginx-module的Nginx(OpenResty自带)。
如果不想编译,直接装OpenResty最省事:

apt install -y curl gnupg2 ca-certificates
# 添加OpenResty官方源并安装,具体源地址以官网为准
apt install -y openresty

装完后执行 openresty -V 确认包含 --with-lua-nginx-module,
再启动Redis:systemctl enable --now redis-server。

配置Key校验和预扣额度

在OpenResty的 nginx.conf 的 http 块内引入计费脚本。
核心逻辑:从请求头取 Authorization,用Key去Redis查用户ID和余额,余额不足直接返回402,余额充足则按预估token预扣。

location /v1/chat/completions {
    access_by_lua_file /etc/nginx/lua/billing.lua;
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
}

billing.lua 里做三件事:

  • 用 ngx.req.get_headers()["authorization"] 取Key,查Redis HGET user:key: uid,查不到返回401。
  • 用 HGET user:balance: balance 读余额,低于单次最低预扣值(比如0.001元)返回402并提示充值。
  • 预扣用 HINCRBYFLOAT user:balance: balance -0.001,同时把本次请求ID和预扣金额写入 HSET pending:,方便后续结算或回滚。

注意预扣值只是占位,最终以响应里的 usage.total_tokens 为准。

响应后按实际token结算

在 location 中加 body_filter_by_lua_file,读取上游返回的JSON,解析 usage.total_tokens,按单价计算实际费用,与预扣值做差额补扣或退还。
流式响应(SSE)要特殊处理:累计拼接chunk,在最后一个chunk里找usage,找不到就按预扣值结算并记录日志,避免漏扣。

结算代码片段示意:

local body = ngx.arg[1]
if body and body:find('"usage"') then
    local total = tonumber(body:match('"total_tokens"%s*:%s*(%d+)'))
    if total then
        local cost = total * unit_price
        redis:hincrbyfloat('user:balance:'..uid, 'balance', pre_deduct - cost)
        redis:hdel('pending:'..req_id)
    end
end

单价建议放在Redis配置里,方便调价不用重启。

避坑指南

  • 流式响应漏扣:SSE的usage可能只在最后一个data块出现,body_filter会被多次调用,务必用缓冲区拼接后再解析,否则大量请求按预扣值结算,长期亏钱。
  • 并发超扣:预扣和结算之间不是原子操作,高并发下可能余额扣成负数。对同一用户加Redis分布式锁,或在预扣时用Lua脚本保证查余额和扣减原子执行。
  • Key泄露:不要把Redis密码和单价硬编码在lua文件里,用环境变量或独立配置文件,文件权限设600。
  • 结算失败回滚:请求超时或上游5xx时,预扣额度要退还,建议用定时任务扫描 pending:* 超过5分钟的记录做补偿。

验证扣费是否生效

用一个测试Key发两次请求,第一次正常调用,第二次把余额改成0再调,预期分别返回200和402。
然后查Redis:

redis-cli HGET user:balance: balance
redis-cli KEYS 'pending:*'

余额应等于初始值减去实际费用,pending 里不应残留当前请求ID。
再对比后端日志里的token数和扣费金额,确认单价计算一致。
流式接口单独测一次,确认最后一个chunk结算后余额正确变动。

如果余额对不上,先看 error.log 里lua是否报解析错误,再检查单价配置是否和代码里读取的key一致。

常见疑问

Q:必须用OpenResty吗?
普通Nginx需要自行编译lua-nginx-module,步骤多且容易版本不匹配;OpenResty已集成,新手优先选它。

Q:token数从哪来?
取决于后端模型接口是否返回usage字段。如果后端不返回,只能在网关层估算,误差较大,建议优先选带usage的接口。

Q:能按请求次数而不是token计费吗?
可以,把结算逻辑改成每次固定扣费即可,但预扣和结算仍要保持原子性,避免并发问题。

分享到:
上一篇
大模型商业授权配置:从申请到部署的完整落地指南
下一篇
大模型Token计费配置:按调用量统计与配额限制落地
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意