一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

PHP 如何封装一个中间件实现不同 AI 服务商计费统计的统一管理

时间:2026-07-10 10:16:56 编辑:袖梨 来源:一聚教程网

中间件应仅拦截 /api/chat、/api/image/generate 等真实调用 AI 服务的路由,排除 /health、/auth/login 等非计费路径及 OPTIONS 预检请求;优先通过路由名判断而非 URL 路径;计费统计宜置于 API 网关后、业务服务前;需为不同服务商实现统一 BillableResponse 接口以适配 token 提取逻辑。

中间件要拦截哪些请求路径才合理

只对真正调用 AI 接口的路由做计费统计,比如 /api/chat/api/image/generate 这类明确由前端发起、后端转发给第三方 AI 服务的请求。别把健康检查 /health、登录 /auth/login 或静态资源也包进去——这些不产生费用,统计反而污染数据。

常见错误是直接在全局中间件里无差别记录所有请求,结果发现账单对不上,因为日志里混进了大量非计费调用。

  • 用 Laravel 的 $request->route()->getName() 或 ThinkPHP 的 Route::current()->getName() 判断路由名更可靠,比靠 URL 路径匹配容错性高
  • 如果用了 API 网关层(如 Kong),计费统计应放在网关后、业务服务前,避免重复或遗漏
  • 务必排除 OPTIONS 预检请求——它们不触发实际 AI 调用,但会被某些框架自动捕获

如何从请求和响应中提取计费关键字段

不同服务商返回结构差异大:openai 在响应头带 x-ratelimit-remainingx-ratelimit-reset,但计费核心得看响应体里的 usageanthropic 返回 content 字段不带 token 数,得靠 usage.input_tokensoutput_tokensqwen(通义千问)则把 usage.total_tokens 放在顶层。

不能写死解析逻辑,否则换一个服务商就得改中间件代码。

立即学习“PHP免费学习笔记(深入)”;

  • 定义统一抽象接口 BillableResponse,要求各服务商适配器实现 getInputTokens()getOutputTokens()
    </li><li>中间件里不做 JSON 解析,只把原始响应体传给对应适配器——避免中间件承担格式转换职责</li><li>若响应失败(HTTP 4xx/5xx),仍需记录失败事件:有些服务商按“调用次数”收费(如早期 Azure OpenAI 某些 SKU),不是只算成功请求</li></ul><H3>计费数据写入时为什么不能直接 INSERT</H3><p>高并发下多个请求几乎同时完成,直接往数据库 <code>INSERT
    计费记录,容易因主键冲突或唯一索引报错(比如同一秒内多个请求用了相同 trace_id)。更糟的是,如果中间件里还顺手更新用户余额表,事务锁表会拖慢整个 API 链路。

    计费是事后审计行为,不是业务强依赖流程。

    • 用 Redis 的 LPUSH 把原始计费事件(含 timestamp、model、tokens、cost、request_id)暂存为队列,格式用 JSON 字符串
    • 单独起一个 Laravel 的 artisan schedule:run 或 Swoole Worker 定时消费队列,批量写入 MySQL 或 ClickHouse
    • 避免在中间件里调用 sleep() 或重试逻辑——超时会传染到前端,必须保证中间件执行时间

    怎么验证中间件没漏记也没多记

    最有效的办法是拿真实流量跑 A/B 对照:一边走老逻辑(SDK 内部手动埋点),一边走新中间件,对比两套数据的 total_tokens 总和与请求量。偏差超过 0.5% 就得查。

    容易被忽略的是异步调用场景——比如用户上传文件后,后端用 dispatch(new AiImageJob()) 异步生成图,这种请求不在 HTTP 生命周期内,中间件根本捕获不到。

    • 对异步任务,要在 Job 的 handle() 开头显式调用 BillingRecorder::recordAsync(...),传入 job_id 替代 request_id
    • 在中间件里加个开关配置 billing.enabled,上线初期先设为 false,用日志输出模拟计费数据,确认字段齐全再开写入
    • 每条计费记录必须带 source 字段(值为 middlewarejob),方便后续归因

热门栏目