mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
feat(channels): 源改为串行 + 按模型节流(照参考 model-gate.ts)
照参考的实测依据:这些平台的**并发配额按模型**分别计量,与"还剩多少 token"
无关(那边实测撞 429 时 token 还剩 299.4 万)。同账号下:
GLM-5.3-Flash 605 次 200 0 次限流 ← 从未撞过
GLM-5.3 74 次 200 21 次重试 6 次最终 429
两条措施缺一不可:
① **串行**(max_concurrent=1):并发发起必然浪费一个配额;
② **最小间隔**(rpm):串行只保证"不重叠"、不保证"有间隔" —— 连续放行的两次
调用可能只隔几十毫秒,仍会撞并发窗口。
此前插件注册源一律 `max_concurrent = 2` 且**从不设 rpm** ⇒ 既会重叠又无间隔。
现全部改为 `max_concurrent = 1` + `rpm = 20`(默认 3 秒一个,可按平台覆盖)。
⚠️ 参考的另一条教训也记进注释了:闸门**只包 fetch,不包 captcha**。
那边第一版把 mint 与 fetch 一起放进闸门,mint 耗时从 200-500ms 暴涨到
2500-3100ms(因为 mint 被串行后变成"排在 N 个人后面再 mint")。
我们的 rpm 节流在内核层、只作用于上游 dispatch,天然不涉及这一点。
顺带:`list_sources` 补暴露 `rpm` —— 运维与判据都要能看到它。只看
max_concurrent 无法区分"串行但有间隔"与"串行且无间隔"(后者仍会撞窗口)。
判据 `TestChannelSourcesAreSerialWithThrottle`:源必须 max_concurrent=1 且 rpm>0。
回归:9 个包全绿。
This commit is contained in:
@ -3050,7 +3050,19 @@ local function syncAccountSource(provider, accountId)
|
||||
base_url = plat.base_url,
|
||||
adapter = plat.adapter or "openai",
|
||||
api_key = tok,
|
||||
max_concurrent = 2,
|
||||
-- ⚠️ max_concurrent=1 + rpm 节流,而不是 2。
|
||||
--
|
||||
-- 照参考 model-gate.ts 的实测依据:这些平台的**并发配额按模型**分别计量,
|
||||
-- 与"还剩多少 token"无关(那边实测撞 429 时 token 还剩 299.4 万)。同账号下:
|
||||
-- GLM-5.3-Flash 605 次 200 0 次限流 ← 从未撞过
|
||||
-- GLM-5.3 74 次 200 21 次重试 6 次最终 429
|
||||
-- 两条措施缺一不可:
|
||||
-- ① **串行**:同一时刻只允许一个上游请求在飞(并发发起必然浪费一个配额)
|
||||
-- ② **最小间隔**:串行只保证"不重叠",不保证"有间隔" —— 连续放行的两次
|
||||
-- 调用可能只隔几十毫秒,仍会撞并发窗口。故用 rpm 让内核把它们隔开。
|
||||
-- 这两条都是**客户端自保**(防患于未然),与"上游明确要求排队"是两回事。
|
||||
max_concurrent = 1,
|
||||
rpm = plat.rpm or 20, -- 默认 3 秒一个请求,可按平台覆盖
|
||||
models = models,
|
||||
}
|
||||
-- 平台的 chat 端点常与 base_url 不是简单拼接(Gemini 走私有
|
||||
@ -4897,7 +4909,9 @@ function plugin.complete_login(req)
|
||||
base_url = plat.base_url,
|
||||
adapter = "openai",
|
||||
api_key = legacyTok,
|
||||
max_concurrent = 2,
|
||||
-- 同 syncAccountSource:串行 + 节流(见那里的长注释)
|
||||
max_concurrent = 1,
|
||||
rpm = plat.rpm or 20,
|
||||
models = (function()
|
||||
local ms = {}
|
||||
local eff = effectiveModels(plat.id)
|
||||
@ -5971,7 +5985,7 @@ function plugin.provider_set_enabled(req)
|
||||
if legacy and legacyTok then
|
||||
__llmsproxy_kernel.call("add_source", { source = {
|
||||
name = "channels-" .. plat.id, base_url = plat.base_url, adapter = plat.adapter or "openai",
|
||||
api_key = legacyTok, max_concurrent = 2,
|
||||
api_key = legacyTok, max_concurrent = 1,
|
||||
models = (function() local ms = {} local eff = effectiveModels(plat.id)
|
||||
for i, m in ipairs(eff) do ms[i] = { id = m, kind = "chat", priority = 20 } end return ms end)(),
|
||||
} })
|
||||
@ -8726,7 +8740,7 @@ function plugin.__sync_source_probe(args)
|
||||
end
|
||||
local test_src = {
|
||||
name = want, base_url = plat.base_url, adapter = plat.adapter or "openai",
|
||||
api_key = tok, max_concurrent = 2, models = models,
|
||||
api_key = tok, max_concurrent = 1, models = models,
|
||||
}
|
||||
if plat.endpoint then test_src.endpoint = plat.endpoint end
|
||||
local rr, rerr = __llmsproxy_kernel.call("add_source", { source = test_src })
|
||||
|
||||
Reference in New Issue
Block a user