![]() | 1 Immortal 2023-12-08 13:01:57 +08:00 有没有可能是 gpt 到达限制了 试试其他平台的接口然后测下并发? |
![]() | 2 ETiV 2023-12-08 13:03:08 +08:00 via iPhone ![]() ??? 你直接问 GPT 不就好了 |
![]() | 4 LemonLeon OP |
5 dxb848295325 2023-12-08 13:36:27 +08:00 我有兴趣,微信 18628069445 |
![]() | 6 kidlj 2023-12-08 13:37:00 +08:00 瓶颈八成在 IO ,特别是网络 IO 。 |
7 deorth 2023-12-08 13:38:31 +08:00 via Android 加服务器 |
![]() | 8 idblife 2023-12-08 13:41:55 +08:00 关注一下,这个项目不错 |
![]() | 9 tonywangcn 2023-12-08 14:00:09 +08:00 感兴趣 wx dG9ueXdhbmdpbw== |
![]() | 10 gongquanlin 2023-12-08 14:07:23 +08:00 之前研究了下这个项目源码,到处都是 case xxxx ,维护起来真 tm 费劲。 能开源确实很值得鼓励,单纯的是我认为里面的设计很难接受,正在开发替代品 |
![]() | 11 lzgshsj 2023-12-08 14:17:19 +08:00 作者就在 v2 |
![]() | 12 fengxsong 2023-12-08 14:29:17 +08:00 ``` if err != nil { fatalLog(...) } return err ``` |
13 kuaner 2023-12-08 14:43:17 +08:00 直接联系作者给出个 Pro 版本 |
![]() | 14 RockChinQ 2023-12-08 14:45:57 +08:00 估计是 上游渠道较慢 导致的利用率低,这几天 OpenAI 确实经常 429 。建议你,后端搭建多个 oneapi 实例 分别接入不同的 OpenAI 账号,最好是分布在不同的服务器上,前端再用一个 oneapi 来做负载均衡。 |
![]() | 15 voidmnwzp 2023-12-08 14:52:41 +08:00 via iPhone 用单个 g 重新封装 epoll 试试 |
![]() | 16 awah 2023-12-08 15:05:57 +08:00 既然明确资源利用率非常低, 那不如直接起多个进程做负载均衡. 简单快捷 |
![]() | 17 lifei6671 2023-12-08 15:10:12 +08:00 你是怎么确定并发已经达到了极限的? |
![]() | 18 cosiner 2023-12-08 15:28:41 +08:00 cpu, mem 都没满,正常应该是可以支撑更多请求的,不会是带宽不够吧 |
![]() | 19 monsterxx03 2023-12-08 15:33:59 +08:00 ![]() 确定上游没到极限的话,大概率是锁竞争过多导致 cpu 利用率上不去。 给个思路,runtime.SetMutexProfileFraction(5) 打开 mutex profiling 然后看 pprof 的 mutex 火焰图,看瓶颈在哪。 简单看了下代码 https://github.com/songquanpeng/one-api/blob/01f7b0186fae589e0e5fb83ab0e6d033ba5339aa/controller/relay-text.go#L376 比如这个地方直接用了一个全局的 httpClient, 里面是从连接池里取连接时候是有锁的,之前碰到过这个问题,优化办法是根据 cpu 核心数实例化多个 client, 每次随机挑一个发请求。 另外 http.Client 的 MaxIdleConnsPerHost 默认值是 2 ,conn 会被频繁回收,试试设置成几百。 |
20 slowman 2023-12-08 15:39:14 +08:00 看起来程序员确实是太多了 |
![]() | 22 cosiner 2023-12-08 16:04:52 +08:00 还不如先看日志,确定问题发生在哪个阶段 |
23 liuzonghao 2023-12-08 16:41:46 +08:00 |
![]() | 24 0x676e67 2023-12-08 16:58:54 +08:00 vw50 算一卦 |
![]() | 25 dw2693734d 2023-12-08 17:01:43 +08:00 io 的问题吧,用这个 pprof 一下: github.com/felixge/fgprof |
![]() | 26 lasuar 2023-12-08 17:09:37 +08:00 绝大部分项目最快遇到瓶颈的位置都是 IO (一般是上行带宽/DB ),其次是某个/些对象的锁竞争激烈,最后是第三方 API 频率限制,最最后是各种原因导致的 CPU/内存资源不足。 一种简单的定位方式是在对应 API 内可能耗时的调用位置前后添加 log 打印时间,观察耗时。 |
![]() | 27 waltcow 2023-12-08 17:36:14 +08:00 |
![]() | 28 isSamle 2023-12-09 16:03:56 +08:00 应该是项目做了限制吧,项目里面故意加锁避免高频用量?还没看源码随机猜的。 |
![]() | 29 LemonLeon OP @tonywangcn 空的,麻烦重新发一下 |
![]() | 31 LemonLeon OP @monsterxx03 你好,方便远程帮我排查一下吗 |
![]() | 32 LemonLeon OP 这里统一感谢大家的回复!还没有找到优化方案,目前正在尝试增加机器性能。 如果你有时间远程协助我,可以添加我的联系方式 v:bitdark |
![]() | 33 tonywangcn 2023-12-10 17:31:05 +08:00 @LemonLeon base64 转下 |
34 ryan961 2023-12-10 17:53:01 +08:00 简单看了下,项目挺简单的,代码量也不多。直接找个有经验深点的重写下应该就行了 |
![]() | 35 kuanat 2023-12-11 00:40:52 +08:00 信息有点少,最好能把部署环境、压测方式都贴上来,这样便于分析。 主要是 4c8G -> 6c8G 就能提升并发,这个现象很难解释。表面上只能判定说,内存不是瓶颈,与 GC 或者内存泄漏无关。 而且 2000/5000 rpm 的尺度是分钟,每秒也就是 30~80 的水平。这个数值过于低了,一般是业务逻辑造成的,而不是技术栈造成的。 另外关于 #19 讨论的锁,相关代码是 oneapi 向外发起链接的逻辑。虽然 net/transport 内部维护的连接池确实是有互斥锁的,但这里 race condition 非常弱。最差的情况等价于是退化到 openai 服务器不支持 keepalive ,每次都需要建立连接。而且每秒不到 100 的并发,基本不可能触发死锁。 |
![]() | 36 LemonLeon OP @kuanat 感谢回复,我调整了测试方法。以下是最新的情况: 1.1 )部署环境:Centos7 Mysql8 nodev16.16.0 go1.20.2 1.2 )测试方法: Windows Python3.8.10 locust 1000 用户并发,测试结果稳定在 300qps 附近(单个 locust 终端) ![]() ![]() 2 ) 2c4g 4c8g 6c16g ,测出来的并发量都是 300 附近。内存,磁盘读写,带宽压力并不大 3 )我推测的原因有两个,要么在 cpu ,要么在数据库。通过提高数据库的最大连接数,并发线程有一点提高。 4 )当用户端发起超多请求时候,数据库提前打开连接等待,然后系统就超出 mysql 最大连接数,并发降低下来。这是我的推测。 如果是这样,那一定有一种方案,是把这些任务都放在内存中处理完了,最后再批量插入数据库中。 5 )我看到有一些中转系统就是基于内存处理的,欢迎大家指正和指路 |
![]() | 38 uRQDd07Pt2UWOtOF 2023-12-11 12:56:37 +08:00 @LemonLeon 你说的是那个 https://proxyxai.com 吧 , 确实很强大 |
![]() | 39 unfurl 2023-12-11 13:47:17 +08:00 看到用的是 locust… 我们内部是禁止使用该工具的,它自身存在性能问题,压不上去 |
![]() | 40 kuanat 2023-12-11 13:55:52 +08:00 @LemonLeon #36 我做了个简单推理,可能需要你实际测试一下。 既然加 cpu 和内存不影响 rps 说明大概率瓶颈应该是在 IO 了。我大致看了一下处理流程,涉及到 IO 的操作就是日志相关的。 https://github.com/songquanpeng/one-api/blob/366b82128f89a328f096da6951cbafebb6b0060f/controller/relay-text.go#L410 这段代码主要功能是在请求结束后结算用量,然后记录。记录的内容本地文件有一份,数据库有一份。本地那一份肯定比数据库快,所以不考虑了。 数据库 IO 涉及三个操作: https://imgur.com/a/OAPZXsl 如果是默认配置( common.LogCOnsumeEnabled=true ),RecordConsumeLog 会产生一次插入操作; 默认 BATCH_UPDATE_ENABLED=false ,那么 UpdateUserUsedQuotaAndRequestCount 和 UpdateChannelUsedQuota 各自都会产生一次查找更新操作。 等于说每个请求都伴随三次数据库写操作。默认 SQL_MAX_OPEN_COnNS= 1000 ,理论并发在 333 左右,和实测比较接近。 当然前提是这三个数据库操作能够在 1s 之内完成(大概率是的)。这个事情不太容易确定,因为 locust 记录的是完成请求的总时间,并不知道中继请求和数据库操作的时间占比。 如果做个粗略估计的话,观察第响应时间的中位数,在测试刚刚开始的时候是 2s ,之后略低于 3s 。猜测当数据库 IO 达到瓶颈的时候,平均要多花接近 1s 等待。 要验证这个猜想,简单的方式是调整 BATCH_UPDATE_ENABLED 启用批量更新,单请求的数据库写入会降至 1 次。或者再提高 SQL_MAX_OPEN_CONNS 的数值。同时可以查看本地日志和 sql 服务器的日志,辅助确认 sql 服务器不是瓶颈。 假如上面的方法无效,那就要考虑 pprof 之类的方式来定位瓶颈了。 |
![]() | 41 guoguoyu 2023-12-18 10:10:41 +08:00 可以试试我的方案,我从 8 9 月就开始处理这个问题了,经过几轮优化,现在 2h2g 都能有很高 QPS ,也帮过好多个人做了优化,看下优化效果: https://www.bilibili.com/video/BV1sj411W71m/ |