免费额度不是无限的:给四个 Cloudflare 账号装一个用量守卫

举报
yd_235936725 发表于 2026/11/10 10:53:28 2026/11/10
【摘要】 我把 AI 推理、书签打标签这些调用都接进了自建网关,网关背后是四个 Cloudflare 账号拼起来的免费额度池。免费额度用完不会提前打招呼,只会在调用时直接报错。于是我写了一个每两小时跑一次的用量巡检:一次查询拿回三个账号维度的用量,按 50%、80%、100% 分级告警,超限的账号自动从网关里降权甚至临时下线,付费账号则退到兜底位置。这篇文章记录这个守卫是怎么搭的,以及几个关键取舍。

一、为什么免费额度需要一个“守卫”
先交代背景。我的自建 AI 网关背后挂了四个 Cloudflare 账号,每个账号每天有 10000 Neurons 的 Workers AI 免费额度,四个加起来就是每天 40000。网关按权重把请求分到四个账号对应的渠道上,平时书签自动打标签、每天早上的资讯简报、偶尔的手动调用都走这里。
这套东西跑起来之后,我发现一个别扭的点:网关本身是看不见剩余额度的。它只知道把请求发出去、收到 200 还是报错。免费额度耗尽的那一刻没有任何预告,正在跑的调用会直接失败——书签打标签失败只是少几个标签,倒不至于天塌下来,但问题是失败是静默的,等我发现往往已经是第二天了。
更麻烦的是四个账号的性质还不一样。其中三个是纯免费账号,额度用完就停;第四个是付费计划,免费的 10000 Neurons 用完之后不会停服,而是开始按量计费,每千 Neurons 收 0.011 美元。平时用量只有每天额度的百分之几,账单基本是零,但万一哪天某个任务失控循环调用,免费账号只是报错,付费账号却是实打实地花钱。同一个“用完”在两种账号上是两种后果,守卫必须分得清。
所以我给自己定了个目标:额度快用完时要提前知道,用完了要自动处理,处理完了要能自己恢复,而且整个过程不能天天在我眼前刷屏——没事的时候就该安静。
二、一次查询拿三项用量
用量数据来自 Cloudflare 的 GraphQL 分析接口。四个账号各发一次查询,每次查询里同时问三组数据:
当天(UTC 零点起)的 Workers AI 推理量,按模型分组,取总 Neurons 数和输入输出 token 数;
当天(UTC 零点起)的 Workers 请求数和错误数;
过去 24 小时的 R2 存储量,取最大的那个 bucket 的体积和对象数。
查询大概长这样(接口地址里的点号两侧加了空格,实际配置里没有空格,原因见文末注):
query($a: String!, $dayStart: String!, $now: String!, $dayAgo: String!) {
viewer {
accounts(filter: {accountTag: $a}) {
ai: aiInferenceAdaptiveGroups(
limit: 100
filter: {datetime_geq: $dayStart, datetime_leq: $now}
) {
count
sum { totalNeurons totalInputTokens totalOutputTokens }
dimensions { modelId }
}
wk: workersInvocationsAdaptive(
limit: 100
filter: {datetime_geq: $dayStart, datetime_leq: $now}
) {
sum { requests errors }
}
r2: r2StorageAdaptiveGroups(
limit: 100
filter: {datetime_geq: $dayAgo, datetime_leq: $now}
) {
max { payloadSize objectCount }
dimensions { bucketName }
}
}
}
}
这里有几个细节值得一提。
第一,时间窗口全部按 UTC 算。Neurons 和 Workers 请求数都是“当日 UTC”口径,UTC 零点重置,也就是北京时间早上八点。写脚本的时候很容易顺手用本地时间当天的零点当起点,那就错了八小时——早上八点前查到的数据会把昨天的尾巴也算进来,百分比虚高。
第二,Neurons 按模型分组返回。这样告警里除了“用了百分之多少”,还能顺带说一句“最大消耗来自哪个模型”。我平时用量小,这个字段基本只是个参考;但真到排查“今天怎么突然用了 8000”的时候,它能立刻告诉我是打标签的视觉模型在烧,还是简报的大模型在烧。
第三,R2 的口径和其他两项不一样。Neurons 和请求数是“当天累计”,R2 是“当前存量”,所以查的是过去 24 小时的最大值,而不是当天的增量。免费额度是每个账号 10 GB 存储,超了也不会立刻停服,但备份文件只进不出的话,存量是单调上涨的,盯着它主要是为了及时收紧备份保留策略。
三、分级阈值,与“同一阈值只报一次”
三项用量的阈值是分开设的:
用量项
免费限额
告警阈值
Workers AI Neurons
10000 / 天 / 账号
50%、80%、100%
Workers 请求数
100000 / 天 / 账号(付费账号为每月 1000 万次含池)
80%、100%
R2 存储
10 GB / 账号
80%、95%
Neurons 从 50% 就开始报,是因为它是消耗最快、后果最直接的一项;Workers 请求数平时只有几百次,80% 才报也不迟;R2 按月口径,95% 是留给备份策略调整的最后窗口。
阈值本身不难,难的是“别重复报”。巡检每两小时跑一次,如果 80% 的告警每次都发,一天能收到六条同样的消息。所以脚本旁边放了一个状态文件,按账号分别记录三项用量“已经报到第几档”。只有当用量跨过一个比已报档位更高的阈值时才发新告警;已经报过的档位,哪怕又查了十次,也静默。
状态文件的重置节奏跟着用量口径走:Neurons 和 Workers 的已报档位在 UTC 跨日时清零,R2 的按月清零。这样每天早上八点额度重置后,告警档位也回到起点,不会因为昨天报过 100% 就导致今天的 50% 被吞掉。
告警正文里还有两个讲究。一是每个账号前面都带前缀,主账号、二号账号、三号账号、四号账号,四个账号共用一套脚本和一个推送通道,不标清楚就分不清是谁在报警。二是同样是 100%,文案要分账号性质写:免费账号写“额度已耗尽,今日经它的推理会报错,明日八点恢复”;付费账号写“免费部分已用完,之后按量计费,请留意账单”。一句话的差别,背后是“停服”和“花钱”两种完全不同的处理方式。
四、告警之外:额度感知调权
只报警是不够的。告警发出来的时候我可能在睡觉,两个小时的巡检间隔里,网关还会继续往已经耗尽的账号上送请求——每次都是注定失败的调用。所以巡检脚本在每次查完用量之后,顺手做第二件事:按各账号 Neurons 的已用百分比,自动调整网关里对应渠道的权重。
权重阶梯是这样定的:
Neurons 已用
渠道权重
50% 以下
10
50%–80%
6
80%–95%
3
95%–100%
1
权重只是“分流偏好”,网关按权重比例选渠道,用得越多的账号分到的新请求越少。真正的硬动作在 100% 那一档:免费账号的渠道直接临时禁用,流量全部偏向其他账号;付费账号的渠道降为兜底优先级,只在其他渠道都不可用时才走它。两个动作都是自动的,次日额度重置后也自动恢复,不用人半夜起来操作。
这里有几个刻意做的克制。
第一,权重阶梯的变化是静默的。只有“禁用、兜底、恢复”这三种状态转换才会发一条告警。权重从 10 降到 6、从 6 降到 3 这种事,每天可能发生好几次,全报出来就是噪音。守卫的原则是:只在“需要人知道”的时候出声。
第二,调权只在“目标变了”的时候才执行。脚本会把上次应用过的渠道状态记在状态文件里,算出来的目标和上次一样就什么都不做;不一样才改数据库、重启网关容器。这样巡检本身是幂等的,重复跑也不会反复重启服务。
第三,某个账号用量查询失败时,绝不碰它的渠道。查不到用量不等于额度用完,拿失败当 100% 处理会把好好的账号误禁用;拿失败当 0% 处理又会把已经耗尽的账号放回分流。两种猜法都可能错,所以最安全的做法是不动——保持上次的状态,等下一次巡检查到真实数据再说。
五、巡检本身也可能坏:失败要节流上报
一个每两小时跑的脚本,自己出故障的概率并不低:凭据权限被收回、接口限流、网络抖动,都有可能。所以巡检的输出只有三种:SILENT、ALERT、ERROR。
SILENT:一切正常,或者告警已经发过。什么都不用做,也不用记日志。
ALERT:有新的阈值被跨过,或者有渠道状态转换。告警正文直接发到聊天,并同步推一份到我自建的推送服务,两个通道同一份文本。
ERROR:检查失败。失败信息同样走双通道报出,但每天最多报一次——接口抖动一下就连发十二条报错,比用量告警本身还吵。
还有一个细节:四个账号是逐个查的,单个账号失败不影响其他三个。四个凭据的权限范围本来就不一样,有两个账号的令牌只有 Workers 相关权限,查别的资源会返回 403;脚本要分得清“这个账号查不到”和“整个检查都挂了”,前者只影响自己,后者才算 ERROR。
上线之前我还留了一个验证用的环境变量开关,可以给主账号模拟一个 Neurons 读数,跑一遍完整的阈值跨越、告警生成和调权流程,确认 100% 那一档真的会禁用渠道、次日真的会恢复。模拟开关只影响主账号的读数,不碰真实用量,验证完就关掉。没经过这一步的自动动作,我不敢让它半夜自己改生产网关。
总结
这个用量守卫满打满算就一个脚本加一个状态文件,每两小时跑一次,做的事其实很简单:查三个数,对三张阈值表,超了就报警,顺手把网关的权重调一下。但它解决的是一个真实存在、又很容易被忽略的问题——免费额度没有仪表盘,网关看不见剩余额度,调用方只会在失败时才发现额度没了。
回头看几个取舍,我觉得都站得住:
查得粗,但查得全。两小时间隔不是实时监控,Neurons 在两小时里冲到 100% 是可能的;但我的日常用量只有额度的百分之几,两小时的粒度足够在出事前两到三档阈值里 catch 住它。真到了用量翻倍的那天,再把间隔缩短也不迟。
只在状态转换时出声。权重阶梯静默执行,告警只报阈值跨越和禁用、兜底、恢复。守卫的价值一半在“报得准”,一半在“平时闭嘴”。
付费账号不是无限额度,只是个安全阀。它存在的意义是让其他三个免费账号出问题时服务不断,而不是让人放心大胆地烧。100% 那一档把它降为兜底,就是为了让“开始计费”这件事尽可能晚发生、尽可能少发生。
失败时不动,比猜着动安全。查不到用量就不调权,报错每天只报一次。自动化的动作越重,失败时的默认行为就越要保守。
免费额度池子搭起来不难,难的是让它在没人盯着的时候也不出事。这个守卫上线到现在,最让我满意的指标不是它报过几次警,而是它大多数时候什么都不发——SILENT,就是它工作正常的样子。
(注:论坛不允许出现外部域名,正文里接口地址的点号两侧加了空格,实际配置里没有空格。)

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。