one-api 高并发状态时通道负载平衡方案的优化讨论

o75abkj4  于 2个月前  发布在  其他
关注(0)|答案(5)|浏览(29)

例行检查

  • 我已确认目前没有类似 issue
  • 我已确认我已升级到最新版本
  • 我已完整查看过项目 README,已确定现有版本无法满足需求
  • 我理解并愿意跟进此 issue,协助测试和提供反馈
  • 我理解并认可上述内容,并理解项目维护者精力有限,不遵循规则的 issue 可能会被无视或直接关闭

1. 功能描述

abilities表中有weight属性,当用户请求时,根据channel的weight权重来随机抽样出channel处理用户的请求。

当rate limit发生时,oneapi自动再重试随机抽样一次,直到超过10次重试或者20次重试后就抛出ratelimit错误给用户,期间的ratelimit错误只做warning记录在error.log里方便root管理员调整渠道分配,而不下抛给用户造成糟糕体验。

2. 应用场景

高并发且多渠道时(每个渠道的TPM等速率指标杂乱不一),容易发生rate limit,根本原因难根据渠道的速率指标进行动态分配。
如果调用端是镜像站这种,那就只能手动再输入一次了,体验较差,体量大时更严重。当然,若调用端(客户端)调用api是用来开发的,也可以在抛出错误时遇到rate limit再尝试一次即可。

3. 可能对开发有帮助的验证经验:

3.1 一般TPM更影响请求

对于高并发请求来说,TPM指标更敏感更容易达到rate limit,RPM相对来说没有那么敏感。
老号的普通规格是200RPM、40000TPM,新号的普通规格是200RPM、10000TPM。
假设用户群请求老号这个渠道,一分钟请求200次,那么平均每次请求只要超过50tokens就会超过TPM,达到rate limit。
但是实际使用中,用户的输入tokens很少为50tokens以下,都是带有上下文的。少的有300tokens,多的有3000tokens。
所以TPM指标更敏感,RPM次之,除非是没有绑卡的号RPM是60。

3.2 速率统计的依据是账号总的请求数,而不是模型分别的请求数

比如在一分钟内同时调用gpt-4-0613模型120次和调用gpt-4-0314模型120次,账号在官网上分别标着gpt-4-0613模型RPM是200,gpt-4-0314模型的RPM是200,这种情况会报rate limit。
请教了多位做的比较大的转发服务供应商,他们说经验上发现速率是以账号来计算的不是以模型来分别计算的。
当然,gpt-3和gpt-4这种跨版本的速率计算是分开的。

3.3 openai每分钟重置TPM统计的逻辑验证

用3.5的5刀账号测试RPM,一分钟内请求三次,然后10秒请求一次。请求三次之后会报rate limit ... Limit: 3 / min. Please try again in 20s.
5刀的RPM为3,并不是指一分钟内只能请求3次,下一分钟后重置服务器的RPM统计后才能使用。实测过了10-20s左右就可以用了。
“Please try again in 20s”并不是指必须要硬等20s才能重新请求,验证发现有时候10s-17s左右就能再重新请求了。
5刀目前的RPM逻辑可能是不稳定且没有规律可言,RPM只是个大概参考值。不知道gpt-4 api账号TPM和RPM指标服务器会不会也是这样判断。
假设gpt-4官方api调用也是这个现象,那么方案C是比较合适的。当rate limit发生时,oneapi自动再随机抽样一次,直到超过10次重试或者20次重试后就抛出ratelimit错误给用户,期间的ratelimit错误只做warning记录在error.log里方便管理员调整渠道,而不下抛给用户造成糟糕体验。

4. 通道负载平衡的几个方案

4.1 现有方案:

某个key调用某个模型时,比如key123调用gpt-4-0613,先抽取key对应的用户组(group)的所有拥有模型gpt-4-0613的且已enabled的channel(查abilities表),抽取出来一个channel集合。
然后随机排序这个集合取第一位为选中的channel,相当于随机平均抽样。

4.2 作者以后可能会用的方案(个人猜测)

abilities表中有weight属性,可能会从随机平均抽样方案改为根据channel设定的权重进行抽样的方案。

4.3 通道负载平衡问题的关键

  1. openai服务器重置TPM、RPM的指标统计,是否有规律可言
  2. 问题的关键是要尽可能减少每次“倒水”时未使用的“杯子空间”,这样可以让每个“杯子”装最多的“水”。最理想的状态,就是这一次倒水刚好把某个水杯填满。(详见下文的问题抽象)

4.4 负载平衡问题的抽象化

打个比喻来说明这个情况。渠道(channel)是装水的水杯,oneapi下游众多用户众多的并发是一次次给水杯倒上不同容积的水,水杯装满水了用户再倒水进去,那就是rate limit错误。水杯每隔一分钟会把现有的水倒掉,重新清空。
而目前的随机平均抽样方案,可以看作用户依次给水杯倒水差不多容积的水。用户1倒给水杯1(channel 1),用户2倒给水杯2(channel 2),用户3倒给水杯3(channel 3)......
这样造成的结果是,体积小的水杯总是会先盛满水,体积大的水杯不一定会盛满水,很容易引发rate limit错误。当然,随机平均抽样方案改为channel权重抽样方案后这个现象会得到缓解,但是并不能根本的解决这个问题。

xkftehaa

xkftehaa1#

我的理想方案是,当某个渠道第一次触发429分组饱和时,将其放入一个“冷却区”中等待一段时间(例如1分钟),然后再将其放出来,而不是不断地重试或直接禁用它。

ar7v8xwq

ar7v8xwq2#

失败重试 #112 ,加权随机 #187 ,这些都是确定会去做的,但是我不保证时间,至于 @mrhaoji 所说的冷却的想法,确实值得借鉴。

bxjv4tth

bxjv4tth3#

关于@mrhaoji所说的冷却的想法,这边尝试补充一下。

每次超过官方限制的速率后,官方服务器都会返回建议重试的信息,例如:

用3.5的5刀账号测试RPM,一分钟内请求三次,请求三次之后会报:rate limit ... Limit: 3 / min. Please try again in 20s.

用有些高配的4账号测试RPM,超过请求后会报:rate limit ... Limit: 4000 / min. Please try again in 50ms.

后台可以正则匹配出需要关闭渠道等待的时间,来比较精准的冷却渠道。

当然,实际测试5刀的时候并不需要等待20s后才能使用,验证发现有时候10s-17s左右就能再重新请求了。

7jmck4yq

7jmck4yq4#

失败重试 #112 已经支持了。

zsohkypk

zsohkypk5#

@songquanpeng 使用k8s部署,如果不区分 master / slave 会有啥影响 ?

相关问题