需要设计一个 api 调用计量计费模块,没有什么成熟的思路。

2022-06-16 12:09:26 +08:00
 cxytz01

如题,产品需要对 api 进行按次数收费,比如 1w 次 /1 元钱,或者每个月 40 元钱 4w 次这样,只是打个比方,价格不重要。

目前就两个思路:

一.每次 api 调用都同步的到数据库里面进行加 1 ,然后判断是否超过阈值,没超过放行,超过了限制。 这里面流程就长了:取得用户 ID ,判断用户 token 权限,对表字段进行加一,然后各种逻辑判断。 如果是网关级别的,会大大降低 api 性能。 优势是精确,劣势是性能低。

二.每次 api 调用直接推到 mq 里面,后方进行 api 统计,异步将结果写入 cache 。 再次 api 调用查 cache ,超出阈值,限流。 优势是高性能,劣势是不精确。

下面是两个业界的 api 收费方式: https://coinmarketcap.com/api/pricing/ https://cloud.tencent.com/document/product/628/39300

请教大家,有没有什么更好的解决方案?

3754 次点击
所在节点    程序员
15 条回复
sadfQED2
2022-06-16 12:15:51 +08:00
用户剩余次数同步到 redis 里面,配合 nginx-redis 插件,直接在网关层处理
theohateonion
2022-06-16 12:17:44 +08:00
一般都是 2 ,还要考虑丢数据,重算,对账等场景。
blackboom
2022-06-16 12:30:19 +08:00
提供一个思路,可以看下开源网页统计实现方式。
y830CAa5nink4rUQ
2022-06-16 12:47:26 +08:00
1w 次 /1 元钱,或者每个月 40 元钱 4w 次

这种对精确到要求不高,多出来的就当做是赠送了。
guisheng
2022-06-16 12:48:33 +08:00
网关过滤器呢 每个用户颁发一个密钥通过 API 携带。redis 控制
helone
2022-06-16 12:55:15 +08:00
其实大部分类似 api 调用的做法都是记录一个调用数,然后定时任务每分钟或者五分钟统计一下全量用户的使用情况,做一些关闭权限之类的操作,不过也可以更精细一些,检查的时候如果用户使用超过 80%或 90%,对这种用户检查频率更高一些
Saxton
2022-06-16 13:40:21 +08:00
一般都是用第二种吧, 异步统计,就跟话费一样,你剩一块钱,假设 1G 一块,你在这几十秒中瞬间就用了 1G 以上,那是不是要做欠费处理呢,不用太纠结。
gam2046
2022-06-16 14:27:19 +08:00
第二种可以满足绝大多数情况,如用用超了,可以挂账,即可调用数为负数,除非以后再也不用,否则都要先冲正。
8rmEHZ8WhVHVOb0E
2022-06-16 14:49:35 +08:00
双模式 设定阈值
例如用户每分钟消耗 100 元,余额 10000 元,那余额大于 1000 元时走模式 2 ,余额次数小于 1000 元时走模式 1
8rmEHZ8WhVHVOb0E
2022-06-16 14:58:04 +08:00
阈值模式
例如用户每分钟消耗 100 元,余额 10000 元,那余额大于 1000 元时走模式 2 ,余额次数小于 1000 元时走模式 1
业务繁忙系统压力大时下调阈值 减少实时判断压力。系统服务能力充足时提高阈值,提高精准度。
该方法可以做到系统压力和精准度的最大平衡 减少负余额 /次数超支的情况

业务流程
1 读取 redis ,判断是否有 到达阈值标识,有进入 2 ,无进入 3
2 读取余额(剩余服务次数),判断是否继续提供服务,其他同 4
3 提供服务
4 队列异步扣取余额(剩余服务次数),扣取后入口余额到达阈值,redis 标识该用户到达阈值标识
zeusho871
2022-06-16 22:07:19 +08:00
用 redis 可能逻辑上容易实现
night98
2022-06-17 01:09:28 +08:00
给你个最简单的方案
meta 服务控制用户使用量数据,增减扔到 mysql ,秒级推送到 redis ,其他服务端启动拉取元数据,像你这种场景一般都是 to b ,初期直接全量拉 redis 的数据就行,然后根据你服务的机器数去除以用户可用的总数,拿到每个用户单独的计数量,扔到类似并发 map 里,这样就从 redis 扣减改成堆内扣减,性能提升一大层,扣减用 cas 类去扣,基本上随随便便百万吞吐,然后扣减不足情况下可以写 rpc 从其他服务借次数,设置限制最多调用三次,三次拿不到去 redis 看还有没有剩余,然后各个服务定期同步已用次数到 redis ,或者 meta 服务直接数据库统计次数推送到 redis ,服务监听并替换现有计数,做的好的话基本上 0 延迟
night98
2022-06-17 01:10:33 +08:00
还有一种就最简单的,redis 集群,单个调用方调用次数顶天 qps2-3 千,直接 redis 扣减,服务重启重新同步库存到 redis ,redis 并发量随随便便几万抗住这个还是很轻松的
i3x
2022-06-17 04:31:07 +08:00
saas 从业者。。。给出我的解答:杜绝客户突发导致超额的方法。

每个实例一组令牌桶。
根据客户套餐不同,会有不同的补充速度,以及令牌桶上限。。

例如客户购买了 1000 万次查询,配额限制 100qps ,突发允许 1000 。则令牌桶最大 1000 ,每秒补充 100 。。。这样就不会有超额问题。
如果同步量较大,精度要求没那么高,也可以延长时间。
同时如果地域广泛,服务器提供多入口多地区。可以设置多组。。。。直到总计数取完。。。各地区可能消耗完毕时间不一致。但是也差不多的。

计费无非是按最终数据库记录的所有的已正确响应应该计费请求的总数。

数据库肯定是记录每一次到达 api 后端的所有查询以及状态、处理结果的吧。。。
至少保存了唯一 id ,时间,相应状态吧。这样对计费足够了。
令牌桶防滥用。计费可以账单制,一分钟或者一个小时汇总一次查询记录计算费用就行了。


处理量级:这套结构分散在不同的机房,总共也没多少算力,半个小时能处理 210M 次简单的 api 查询。。。测试的 api 数据细碎繁多但是逻辑简单。。。。。
Abbeyok
2022-06-17 08:02:11 +08:00
用 redis.incrby

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/859989

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX