请求策略配置
Root 配置请求文本过滤、会话保持与重试预算、渠道健康检查与自动禁用规则,并了解整体保存方式和请求决策记录。
- 在「系统设置」左侧导航中展开「请求策略」即可进入三个分区,地址为
/system-settings/request-policies,仅 Root 可访问。
请求策略配置简介
请求策略决定一个请求在发往上游前是否被拦截、优先使用哪个渠道、失败后是否重试,以及渠道何时被自动禁用或恢复。请求策略包含三个分区:
其他入口(以下跳转链接只对 Root 显示):
- 渠道列表页标题旁的徽标「最大重试: N」显示当前的「最多重试次数」。Root 点击徽标(提示为「重试设置」)可跳转到「会话与重试」;Admin 只能看到数值。
- 编辑渠道时,「异常自动禁用」开关下方的说明显示「参与自动停用」或「不参与自动停用」,以及「来源: …」;其后的「请求策略」链接跳转到「渠道健康」。
- 编辑 API 密钥时,分组为
auto会出现「跨分组重试」开关,其说明末尾的「请求策略」链接跳转到「会话与重试」。
配置分区
三个分区各有自己的保存按钮,分别提交,但写入的是同一套请求策略配置,校验和写入规则见保存与生效。
请求检查
页面顶部显示「来源:全局设置。修改后保存生效。」。下方的「请求文本过滤」用于在请求发往上游前按关键词拦截请求,其下的灰色说明概括了匹配方式和检查范围,详见下文「匹配与拦截规则」。
- 请求策略-请求检查

开关上方的状态提示按当前表单(包括尚未保存的修改)实时显示:
- 两个开关都已开启且关键词列表非空时,显示「按当前表单设置,提示词文本过滤已生效。」
- 其他情况显示「提示词文本过滤需要同时开启两个开关,并配置非空的敏感词列表。」
| 页面字段 | 配置键 | 默认值 | 校验与范围 | 说明 |
|---|---|---|---|---|
| 启用过滤 | CheckSensitiveEnabled | false | 布尔 | 检测到敏感关键词时阻止消息。 |
| 检查用户提示 | CheckSensitiveOnPromptEnabled | false | 布尔;作为「启用过滤」的子项缩进显示,「启用过滤」关闭时置灰,但保留原值 | 启用后,提示将在到达上游模型之前被扫描。必须与「启用过滤」同时开启才生效。 |
| 已阻止的关键词 | SensitiveWords | 空 | 多行文本,每行一个词;匹配时去掉首尾空白并忽略空行 | 每行代表一个关键词。留空以禁用列表,但保留开关状态。即留空后不拦截任何请求,两个开关保持原状。占位文字为「每行输入一个关键词」。 |
- 匹配与拦截规则
- 按不区分大小写的子串匹配:请求文本中包含任一关键词即命中。
- 检查对象是从请求中提取、用于计费估算的合并文本,例如消息文本、工具名和参数;不检查图片、音频和生成的响应内容。
- 命中后,请求在发往上游前被拒绝,返回 HTTP 500,错误码为
sensitive_words_detected,错误消息形如user sensitive words detected: <命中词> (request id: …)。命中词为该关键词的小写形式;匹配到第一个关键词即停止,因此消息中通常只有一个词。 - 被拒绝的请求不会重试,不影响渠道健康状态,也不会触发自动禁用。
- 该功能只做拦截,不替换或遮盖文本,也不过滤上游返回的内容。
- 命中敏感词时返回的是 HTTP 500,客户端会把它当作服务端错误处理,需要按错误码
sensitive_words_detected区分。 - 错误消息会把命中的关键词回显给调用方。词表本身需要保密时,应考虑这一点。
- 保存
页头按钮为「保存敏感词」。没有修改时点击不会发出请求,也不显示提示。
会话与重试
本分区由「会话默认设置」「会话规则」「重试预算」三张卡片组成,共用页头的「保存更改」按钮,点击一次即把三张卡片的修改一起提交。
下图为本分区的整体布局。图中「会话缓存设置」为展开后的状态(默认折叠);底栏「缓存条目」的容量显示为 0,是因为截图环境使用了 Redis。
- 请求策略-会话与重试

「会话保持」即旧版的「渠道亲和性」。部分确认框和日志仍使用旧称,例如「确认清空全部渠道亲和性缓存」「渠道亲和性:上游缓存命中」。
- 会话默认设置
| 页面字段 | 配置键 | 默认值 | 校验与范围 | 说明 |
|---|---|---|---|---|
| 启用会话保持 | channel_affinity_setting.enabled | true | 布尔 | 总开关。关闭后不再匹配会话规则、不读写会话绑定,规则中的参数覆盖模板也不再套用。 |
| 会话保持(单选) | channel_affinity_setting.session_mode | 空,显示为「优先原渠道,失败允许切换」 | 不保持 / 优先原渠道,失败允许切换 / 必须使用原渠道 | 「启用会话保持」下方的三张单选卡片,页面上没有标题,本文称为「会话保持」。全局默认模式,只对「会话保持」设为「继承全局默认」的规则生效。「优先原渠道,失败允许切换」旁显示提示「会降低缓存命中率」。 |
| 切换成功后更新会话绑定 | channel_affinity_setting.switch_on_success | true | 布尔;显示为单选卡片下方的缩进子项;关闭「启用会话保持」时置灰 | 后续请求改用新渠道。开启时绑定实际成功的渠道;关闭时保留首次分配的渠道。 |
| 渠道不可用时保留会话绑定 | channel_affinity_setting.keep_on_channel_disabled | false | 布尔;置灰条件同上 | 关闭时清除该绑定。开启后,绑定的渠道被禁用或不再适用于当前分组和模型时,仍保留这条绑定。 |
| 最多缓存会话数 | channel_affinity_setting.max_entries | 100000 | 非负整数 | 位于折叠区「会话缓存设置」。内存缓存的容量,填 0 时按 100000 处理;修改后需重启才生效,使用 Redis 时不使用该值。 |
| 默认会话有效期(秒) | channel_affinity_setting.default_ttl_seconds | 3600 | 非负整数 | 位于折叠区「会话缓存设置」。规则 TTL 为 0 时使用该值;填 0 时按 3600 处理。 |
三种会话保持模式
| 模式 | 规则命中后的行为 |
|---|---|
| 不保持 | 规则仍会匹配,规则中的参数覆盖模板照常生效,但不读取也不写入会话绑定,按正常方式选择渠道。 |
| 优先原渠道,失败允许切换 | 首次尝试优先使用该会话已绑定的渠道;失败后按正常重试流程切换到其他渠道。 |
| 必须使用原渠道 | 尚无绑定时按正常方式选择渠道,请求成功后建立绑定。但只要命中规则,本次请求的任何失败都不再重试,即使该会话还没有绑定渠道。已有绑定但绑定的渠道不可用时,直接返回 HTTP 503,错误信息为 strict_session_binding_unavailable。 |
- 关闭「启用会话保持」后,两个绑定开关置灰;「会话保持」单选仍可修改,但在重新开启总开关前不起作用。
- 「会话缓存设置」默认折叠,展开后才显示两个缓存字段。
- 会话规则
会话规则定义如何从请求中识别同一会话,以及命中后如何保持该会话已使用的渠道;规则本身不指定渠道,渠道仍按正常方式选出后再绑定。卡片标题旁显示规则数量。
每条会话绑定在缓存中占一个条目:「缓存条目」即当前保存的绑定数,清空缓存即解除这些绑定,之后的请求重新选择渠道。
规则弹窗中的「保存」只更新页面上的规则草稿。添加、编辑、删除规则,填充模板,或在 JSON 模式中修改后,都必须点击页头「保存更改」才会提交;离开页面时没有未保存提醒,未提交的修改会丢失。
- 规则可在「可视化」和「JSON」两种模式间切换。JSON 模式下「填充模板」和「添加规则」不可用;JSON 不是数组或格式错误时,无法切回可视化模式。
- 没有规则时显示「暂无规则」。
- 卡片底栏显示「缓存条目」,格式为“已用 / 容量”,读取失败时显示「无法展示」。使用 Redis 时,容量显示为
0。
从零配置会话保持
- 在「会话默认设置」中确认「启用会话保持」已开启。新规则的「会话保持」默认为「继承全局默认」,因此全局「会话保持」不能选「不保持」。这里的修改在第 3 步一并保存。
- 点击「添加规则」→「空白规则」,填写「名称」「模型正则」和至少一个「Key 来源」,然后点击弹窗中的「保存」,字段说明见下文「添加或编辑规则」。新规则排在表格末尾,其「会话保持」列不应显示「不保持」。
- 规则按列表顺序匹配,条件不要与前面的规则重叠,否则请求会先命中前面的规则(见下文「匹配顺序与注意事项」)。可视化模式不能调整顺序,需要时在 JSON 模式中调整。
- 「Codex CLI」「Claude CLI」两个模板与下方的两条内置规则相同,内置规则仍在时无需添加;删除过内置规则时,才需要用模板重新添加。
- 点击页头「保存更改」,提示「保存成功」即表示已提交;校验失败时的提示见保存与生效。
- 发送一个满足该规则全部条件、使用尚未绑定过的 Key 值的请求。请求成功(HTTP 状态码小于 400)后才会写入绑定;被固定到某个渠道的请求不经过会话规则。然后点击卡片底栏的「刷新缓存」(缓存统计不会自动更新),确认该规则行的「缓存」列和「缓存条目」都已增加。如何确认后续请求用上了这条绑定,见变更后验证第 4 条。
默认有两条内置规则,二者都附带请求头透传的参数覆盖模板:
| 规则名 | 模型正则 | 路径正则 | Key 来源 | 会话保持 |
|---|---|---|---|---|
codex cli trace | ^gpt-.*$ | /v1/responses | gjson:prompt_cache_key | 必须使用原渠道(规则单独设置) |
claude cli trace | ^claude-.*$ | /v1/messages | gjson:metadata.user_id | 必须使用原渠道(规则单独设置) |
两条内置规则,以及通过「填充模板」或「添加规则 → Codex CLI / Claude CLI」生成的规则,默认都是「必须使用原渠道」,命中后请求失败也不会重试。
如需失败时切换渠道:编辑规则,把「会话保持」改为「优先原渠道,失败允许切换」(或改为「继承全局默认」,并确认全局模式不是「必须使用原渠道」),在弹窗中点击「保存」后,再点击页头「保存更改」。
表格各列
| 列 | 显示内容 |
|---|---|
| 名称 | 规则名,下方列出模型正则;为空时显示「所有模型」。 |
| Key 来源 | 来源类型,以及键名或路径。 |
| 会话保持 | 实际生效的模式,以及模式来源:「规则单独设置」「继承全局默认」或「全局已禁用」。 |
| TTL | 「N 秒」或「全局默认」。 |
| 作用域 | 「分组」「模型」「规则」标记,对应规则中开启的「包含分组」「包含模型」「包含规则名」。 |
| 缓存 | 该规则的缓存条目数;规则未开启「包含规则名」时显示「不适用」。 |
| 操作 | 编辑规则;「更多操作」菜单中有「删除规则」,开启了「包含规则名」的规则还有「清空该规则缓存」。 |
操作与生效方式
| 操作 | 生效方式 | 说明 |
|---|---|---|
| 添加规则 → 空白规则 / Codex CLI / Claude CLI | 草稿 | 打开规则弹窗,模板会预填对应内容。 |
| 填充模板 | 草稿 | 追加 Codex CLI 和 Claude CLI 两条规则,重名时自动改名;已有规则时先弹出确认,完成后提示「模板已追加」。 |
| 编辑规则 / 删除规则 | 草稿 | 删除前确认,提示「删除会话规则“…”?保存更改后生效。」 |
| 切换可视化 / JSON | 草稿 | 只改变编辑方式。 |
| 刷新缓存 | 只读 | 重新读取缓存条目数和容量。 |
| 清空全部缓存 | 立即生效 | 确认框标题为「确认清空全部渠道亲和性缓存」,与「保存更改」无关。 |
| 清空该规则缓存 | 立即生效 | 位于规则行的「更多操作」菜单,只有开启了「包含规则名」的规则才显示该项。 |
- 添加或编辑规则
点击「添加规则」并选择「空白规则」「Codex CLI」或「Claude CLI」,或点击规则行的编辑按钮,即可打开规则弹窗。下图为空白规则并展开「高级设置」后的状态:输入框中的灰色文字都是占位示例,不是默认值;TTL 中的 0、「会话保持」下拉框、Key 来源类型 gjson 和三个「包含…」开关显示的是实际默认值。
- 请求策略-添加会话规则

基础参数
| 页面字段 | 规则 JSON 字段 | 默认值(空白规则) | 校验与范围 | 说明 |
|---|---|---|---|---|
| 名称 | name | 空 | 必填;留空时点击「保存」,弹窗不关闭,也不显示提示 | 用于识别规则;开启「包含规则名」时也参与缓存键。建议不同规则使用不同名称。 |
| 模型正则(每行一个) | model_regex | 空 | 必填,至少一行;完全留空时同「名称」,只填空白时提示「至少需要一个模型正则匹配模式」 | 对请求模型名做 Go 正则匹配,任一行匹配即可。需要完整匹配时使用 ^ 和 $,例如 ^gpt-4o.*$。 |
| 路径正则(每行一个) | path_regex | 空 | 可选 | 对请求 URL 路径做正则匹配,任一行匹配即可;留空表示不限路径。 |
| 会话保持 | session_mode | 继承全局默认 | 继承全局默认 / 不保持 / 优先原渠道,失败允许切换 / 必须使用原渠道 | 下方提示「全局默认:…」,显示当前全局模式。 |
| Key 来源 | key_sources | 1 行 gjson,值为空 | 至少一个有效来源,否则提示「至少需要一个有效的密钥来源」 | 用于识别同一会话的值。点击右侧「添加」可增加来源,行尾按钮可删除;按顺序取第一个非空值,不会拼接。标题下方列出常用 Key:id、token_id、token_key、token_group、group、username、user_group、user_email、specific_channel_id。 |
Key 来源类型
| 类型 | 填写内容 | 说明 |
|---|---|---|
context_int | 请求上下文键名,例如 token_id | 读取上下文中的正整数并转换为字符串;值不存在或不大于 0 时尝试下一个来源。 |
context_string | 请求上下文键名,例如 username | 读取上下文字符串并去除首尾空白;空值时尝试下一个来源。 |
request_header | 请求头名称,例如 X-Session-ID | 读取指定请求头并去除首尾空白;客户端需要实际携带该请求头。 |
gjson | JSON Body 的 GJSON 路径,例如 metadata.conversation_id | 从请求体中提取值;路径不存在或结果为空时尝试下一个来源。 |
高级设置
| 页面字段 | 规则 JSON 字段 | 默认值(空白规则) | 校验与范围 | 说明 |
|---|---|---|---|---|
| User-Agent include(每行一个) | user_agent_include | 空 | 可选 | 对请求的 User-Agent 做不区分大小写的包含匹配,任一行满足即可,例如 curl。不是正则;留空不限制,填写后不带 User-Agent 的请求一律不匹配该规则。 |
| Value 正则 | value_regex | 空 | 可选 | 用 Go 正则校验提取到的 Key 值,不用于截取或替换。不通过时跳过整条规则。 |
| TTL(秒,0 表示默认) | ttl_seconds | 0 | 非负整数;在 JSON 模式中写入负数时,后端拒绝保存并报 negative affinity TTL | 0 表示使用「默认会话有效期(秒)」;正数为该规则绑定的有效期。 |
| 参数覆盖模板 (JSON) | param_override_template | 空 | 必须是 JSON 对象;不合法时提示「参数覆盖模板中的 JSON 格式无效」或「参数覆盖模板必须是 JSON 对象」 | 规则命中后与所选渠道的参数覆盖合并。普通同名键保留渠道值;operations 数组按规则模板在前、渠道操作在后的顺序合并。完整语法见参数覆盖系统。 |
| 包含分组 | include_using_group | 开启 | 布尔 | 把当前使用的分组加入缓存键,隔离不同分组下的相同 Key。 |
| 包含模型 | include_model_name | 关闭 | 布尔 | 把请求模型名加入缓存键,隔离不同模型下的相同 Key。 |
| 包含规则名 | include_rule_name | 开启 | 布尔 | 把规则名加入缓存键;按规则统计和清空缓存依赖此项。关闭后,不同规则在其他缓存键组成相同时可能共用绑定。 |
匹配顺序与注意事项
- 规则按列表顺序逐条检查。某条规则同时满足以下条件即生效,后面的规则不再检查(即使该会话还没有绑定):
- 模型、路径、User-Agent 条件都匹配;
- 取到非空 Key,且该值通过 Value 正则校验。
- 多个 Key 来源只取第一个非空值。该值未通过 Value 正则时,跳过整条规则,不会再尝试该规则后面的 Key 来源。
- 模型正则为空的规则不会匹配任何请求,即使表格中显示「所有模型」。弹窗要求至少填写一行,这种规则只会通过 JSON 模式写入。
- 规则没有设置会话保持模式时(例如两条内置规则,以及从旧版本保留下来的规则),按旧字段
skip_retry_on_failure显示为「必须使用原渠道」(值为true)或「优先原渠道,失败允许切换」,来源为「规则单独设置」。在弹窗中打开时预填同样的模式,保存后写入明确的模式。 - 弹窗中的「取消」放弃本次编辑;「保存」只更新草稿,见「会话规则」中的提示。
- 提交时后端会编译所有规则的模型正则、路径正则和 Value 正则;任一正则不合法,整次保存都会被拒绝,错误形如
rule "<规则名>": error parsing regexp: …。
- 重试预算
| 页面字段 | 配置键 | 默认值 | 校验与范围 | 说明 |
|---|---|---|---|---|
| 最多重试次数 | RetryTimes | 0 | 整数 0–99(后端只要求不小于 0) | 不含首次,按分组计算(见下方「重试如何进行」第 2 条)。默认 0 表示失败后不重试。 |
| 自动重试状态码 | AutomaticRetryStatusCodes | 100-199,300-399,401-407,409-499,500-503,505-523,525-599 | 逗号分隔的状态码或闭区间,取值 100–599;格式无效时提示「状态码规则无效」;留空表示不按状态码重试 | 2xx、504、524 始终排除。占位文字为「例如 401、403、429、500-599」。保存时相邻区间会合并,见保存与生效。 |
重试如何进行
- 总尝试次数为 1 加「最多重试次数」。每次重试都会重新选择渠道,并依次使用更低一级的渠道优先级;优先级用完后停留在最低一级,可能再次选中同一个渠道。首次尝试使用了会话绑定的渠道时,第一次重试从最高优先级开始。
- API 密钥的分组为
auto且开启了「跨分组重试」时,每个分组各有一份重试次数:当前分组用完后切换到下一个分组,并从该分组的最高优先级开始。 - 每次失败后按以下顺序判断,满足任一项即停止重试:
- 命中「必须使用原渠道」的规则;
- 请求被固定到某个渠道;
- 错误被标记为不可重试;
- 重试次数已用完;
- 状态码为 2xx、504、524,或上游响应体无法解析;
- 状态码不在「自动重试状态码」中。
- 两种例外:
- 渠道类错误(错误码以
channel:开头,例如渠道没有可用密钥、密钥无效、参数覆盖配置无效、模型映射错误)只检查第 1、2 项,之后直接重试,总尝试次数仍受「最多重试次数」限制。 - 状态码不在
100–599范围内时,检查完第 1–4 项后直接重试,不检查第 5、6 项。
- 渠道类错误(错误码以
- 异步任务提交(如视频生成)使用内置规则,不读取「自动重试状态码」:429、307 和除 504、524 外的 5xx 重试;2xx、400、408、504、524 不重试;其余状态码中,本地错误不重试,上游返回的错误(例如 401、403、404)重试。「最多重试次数」、固定渠道和「必须使用原渠道」对它同样有效。
渠道健康
- 请求策略-渠道健康

页面顶部的状态说明随表单变化:
- 固定显示「来源:全局设置。修改后保存生效。」
- 「失败时禁用」开启时显示「各渠道还需开启“自动禁用”,全局禁用规则才会对其生效。」;关闭时显示「按当前设置,所有渠道的自动停用均不生效。」这里的“自动禁用”指渠道编辑中的「异常自动禁用」开关,渠道编辑「路由策略」区块中也显示为「自动封禁」。
- 「成功后重新启用」开启而「定期渠道测试」关闭时,另外显示「定时恢复未运行,批量测试仍可恢复被自动停用的渠道。」
- 渠道健康检查
| 页面字段 | 配置键 | 默认值 | 校验与范围 | 说明 |
|---|---|---|---|---|
| 定期渠道测试 | monitor_setting.auto_test_channel_enabled | false | 布尔 | 按所选检查模式在后台运行检查。 |
| 渠道测试模式 | monitor_setting.channel_test_mode | scheduled_all | 三选一,见下表 | 下方说明随所选模式变化。 |
| 测试间隔 (分钟) | monitor_setting.auto_test_channel_minutes | 10 | 整数,最小 1,否则提示「间隔必须至少为 1 分钟」 | 定时渠道检查的执行间隔。选择「仅检查被自动禁用的渠道」时,说明变为「系统检查自动禁用渠道是否可恢复的频率」。 |
| 渠道测试并发数 | monitor_setting.channel_test_concurrency | 1 | 整数 1–32 | 同时测试的最大渠道数(1-32)。 |
| 成功后重新启用 | AutomaticEnableChannelEnabled | false | 布尔 | 定时或批量检查成功后,可恢复被自动停用的渠道;人工停用的渠道保持停用。 |
只有「渠道测试模式」和「测试间隔 (分钟)」嵌套在「定期渠道测试」下;「定期渠道测试」关闭时这两项不置灰,仍可修改并保存,但定时测试不会运行。「渠道测试并发数」和「成功后重新启用」不受该开关影响,对渠道管理页的「测试所有渠道」同样有效。
渠道测试模式
| 模式 | 测试范围 | 可禁用 | 可恢复 |
|---|---|---|---|
主动检查全部渠道(scheduled_all) | 除手动禁用外的全部渠道,用于主动发现故障并自动恢复渠道。 | 是 | 是 |
主动检查已开启自动禁用的渠道(auto_ban_only) | 只检查开启了「异常自动禁用」的渠道;未开启该选项和手动禁用的渠道不会被检查。 | 是 | 是 |
仅检查被自动禁用的渠道(passive_recovery) | 不检查正常渠道,只复查被系统自动禁用的渠道,并在恢复后重新启用。 | 否 | 是 |
「渠道测试模式」只决定定时测试的范围。「测试所有渠道」始终检查除手动禁用外的全部渠道。
手动禁用的渠道不会被自动恢复。
- 自动禁用规则
| 页面字段 | 配置键 | 默认值 | 校验与范围 | 说明 |
|---|---|---|---|---|
| 失败时禁用 | AutomaticDisableChannelEnabled | false | 布尔 | 将停用规则应用于上游请求错误,以及定时或批量健康检查。渠道本身还需开启「异常自动禁用」。 |
| 健康检查耗时阈值(秒) | ChannelDisableThreshold | 5 | 非负数或留空;校验提示为英文 Enter a non-negative number or leave empty | 全局和渠道自动停用均开启时,定时或批量健康检查耗时超过此阈值可触发停用。填 0 或留空表示不按耗时停用;该阈值不作用于真实请求。 |
| 自动禁用状态码 | AutomaticDisableStatusCodes | 401 | 格式同「自动重试状态码」;无效时提示「无效的状态码规则:…」,输入与归一化结果不同时显示「已归一化:…」 | 接受逗号分隔的状态码和包含性范围。即单个状态码或闭区间,例如 401,403,500-503。 |
| 失败关键词 | AutomaticDisableKeywords | 7 条内置关键词,每行一条 | 多行文本 | 如果上游错误包含以下任何关键字(不区分大小写),渠道将自动禁用。 |
内置失败关键词为:Your credit balance is too low、This organization has been disabled.、You exceeded your current quota、Permission denied、The security token included in the request is invalid、Operation not allowed、Your account is not authorized。
何时触发自动禁用
| 场景 | 判断依据 | 说明 |
|---|---|---|
| 真实请求失败 | 渠道类错误、「自动禁用状态码」、「失败关键词」 | 不比较耗时;被标记为不可重试的错误不触发禁用,但渠道类错误除外。 |
| 定时测试或「测试所有渠道」 | 同上,另外比较「健康检查耗时阈值(秒)」 | 「仅检查被自动禁用的渠道」模式不禁用渠道。 |
| 单个渠道测试 | — | 既不禁用也不恢复渠道。 |
- 以上场景都要求全局「失败时禁用」和渠道「异常自动禁用」同时开启。
- 多 Key 渠道只禁用出错的那个 Key;所有 Key 都被禁用后,整个渠道才变为自动禁用。
- 自动恢复与通知
- 恢复条件:开启「成功后重新启用」,渠道状态为自动禁用,并在定时测试或「测试所有渠道」中测试成功;全局「失败时禁用」开启时,测试耗时还不能超过「健康检查耗时阈值(秒)」。单个渠道测试不会恢复渠道,手动禁用的渠道也不会恢复。
- 自动禁用和自动恢复都会发送通知。接收者是开启了「渠道通知」的已启用管理员(Admin 和 Root);从未设置过该开关时,只有 Root 默认接收。各管理员可在个人设置中开关「渠道通知」。
- 同一渠道同一状态的通知对每位管理员限频,默认 10 分钟内最多 2 条,可通过环境变量
NOTIFY_LIMIT_COUNT、NOTIFICATION_LIMIT_DURATION_MINUTE调整。
- 运行条件
- 定期测试只在主节点运行,
NODE_TYPE=slave的节点不运行。测试按间隔排队,上一轮未结束时不会重复启动。 - 环境变量会覆盖页面值:设置
CHANNEL_TEST_FREQUENCY(正整数)时,强制开启定期测试,间隔取该值(分钟),模式固定为「主动检查全部渠道」;设置CHANNEL_TEST_ENABLED(布尔值)时,强制设定「定期渠道测试」开关。后者在前者之后应用,设为false时仍会关闭定期测试。
保存与生效
- 三个分区分别保存,每次只提交本分区中有变化的项;成功后提示「保存成功」。「会话与重试」和「渠道健康」没有修改时提示「没有需要保存的更改」,「请求检查」没有修改时不做任何提示。
- 后端先把提交的项合并进整套请求策略并整体校验,再在一个事务中写入:任一项不合法,本次提交的所有项都不会写入。这与「安全与限制」等设置域逐项保存的方式不同。
- 校验失败时的提示:
- 多数字段先在前端校验,不合法时不会提交。
- 后端校验失败时,以弹出提示显示后端返回的英文原文,常见于规则正则或 JSON 模式中的修改,例如
rule "<规则名>": error parsing regexp: …、negative affinity TTL、invalid session mode for rule "<规则名>"。 - 「会话与重试」还会在卡片下方用红字显示后端返回的错误;该分区有修改且存在无效值时,底部提示「请修正无效配置后再保存。」
- 修改「自动重试状态码」或「自动禁用状态码」并保存时,前端会先合并相邻区间再提交,例如
409-499,500-503会合并为409-503,覆盖的状态码不变。 - 请求策略没有版本冲突检测,多人同时修改时,后保存的覆盖先保存的。离开页面时也没有未保存提醒,未保存的修改会丢失。
- 保存后当前节点立即更新;多节点部署中的其他节点按
SYNC_FREQUENCY周期(默认 60 秒)重新载入,同步完成前各节点可能短暂不一致。 - 「最多缓存会话数」只在首次使用会话缓存时读取,修改后需重启服务才会改变内存缓存容量;使用 Redis 时不适用。「默认会话有效期(秒)」对之后新写入的绑定立即生效。
请求决策记录
请求策略会记录每个请求的路由与重试决策,供排查使用。
- 位置:使用日志中某条记录的「详情」→「请求策略决策」。只有 Admin 和 Root 能看到。
- 内容:按步骤列出选择的渠道、命中的会话规则、失败原因、重试或停止的判断及其依据来源,以及耗时、分组、状态码和对渠道健康的处理。
- 成功请求的记录随消费日志写入,需要开启运维配置中的「记录配额使用量」(默认开启)。
- 失败尝试的记录随错误日志写入,只有设置环境变量
ERROR_LOG_ENABLED=true时才会写入。请求最终失败时,不会再单独写一条汇总记录。 - 以下请求不会留下决策记录:被敏感词拒绝的请求,它们在进入重试流程、发往上游之前就已结束,既不写消费日志也不写错误日志;命中「必须使用原渠道」但绑定渠道不可用、直接返回 HTTP 503 的请求。
变更后验证
- 刷新浏览器页面后逐个打开三个分区,确认数值与保存的一致。
- 开启请求文本过滤后,用包含测试词的请求验证:应返回 HTTP 500 和错误码
sensitive_words_detected。 - 把「最多重试次数」设为
1以上,用一个可控的失败渠道(例如使用无效密钥的测试渠道)发送请求,在使用日志详情的「请求策略决策」中核对重试次数和停止原因。若所有尝试都失败,需先设置环境变量ERROR_LOG_ENABLED=true,否则使用日志中没有该请求的决策记录。 - 验证会话规则:按会话与重试中「从零配置会话保持」第 4 步,用一个尚未绑定过的 Key 值发送满足规则条件的请求。请求成功后必须先点击「刷新缓存」(统计不会自动更新),再查看该规则行的「缓存」列是否增加。然后用同一 Key 再请求一次,在使用日志中确认两条记录的渠道 ID 相同。渠道 ID 右上角的琥珀色 ✦ 表示该请求关联了会话规则,悬停可看到规则名和分组:
- 规则没有参数覆盖模板时,✦ 只在首次尝试使用了已有绑定时出现:新 Key 的第一条请求没有 ✦,第二条起才有。
- 规则带参数覆盖模板时(包括两条内置规则),只要命中规则就显示 ✦,第一条请求和「不保持」模式下也会显示,因此 ✦ 不能证明绑定已生效,应以渠道 ID 和「缓存」列为准。
- 用「测试所有渠道」验证自动禁用原因和自动恢复;避免在业务高峰期制造大量失败。
常见问题
- 敏感词没有拦截:确认「启用过滤」和「检查用户提示」都已开启、关键词列表非空;匹配方式为不区分大小写的子串匹配;图片、音频和响应内容不检查。该检查只作用于普通中转请求和 Responses WebSocket 请求,Midjourney 和异步任务的提交不经过此检查。
- 命中敏感词后客户端收到 500:这是当前实现,客户端应按错误码
sensitive_words_detected识别并处理。 - 重试没有生效:依次检查:
- 「最多重试次数」是否仍为默认值
0; - 失败的状态码是否在「自动重试状态码」中;
- 请求是否命中了「必须使用原渠道」的规则,包括两条内置 CLI 规则;
- 请求是否被固定到某个渠道;
- 是否属于 2xx、504、524 这类始终不重试的情况;
- 可用渠道是否只有一个,或最低一级优先级只有同一个渠道:此时仍会重试,但可能再次选中同一渠道,看起来像没有重试。
- 「最多重试次数」是否仍为默认值
- 命中内置 CLI 规则的请求失败后不重试:
gpt-*模型的/v1/responses请求体带有prompt_cache_key,或claude-*模型的/v1/messages请求体带有metadata.user_id时,会命中两条内置 CLI 规则。它们默认是「必须使用原渠道」,命中后即使还没有绑定渠道也不重试。把这两条规则的「会话保持」改为「优先原渠道,失败允许切换」,或改为「继承全局默认」并确认全局模式不是「必须使用原渠道」;在弹窗中点击「保存」后,再点击页头「保存更改」。 - 渠道被自动禁用:检查全局「失败时禁用」、渠道「异常自动禁用」、「自动禁用状态码」和「失败关键词」;耗时阈值只在定时测试和「测试所有渠道」中比较。
- 渠道没有自动恢复:需要开启「成功后重新启用」,并有一次成功的定时测试或「测试所有渠道」;全局「失败时禁用」开启时,测试耗时不能超过「健康检查耗时阈值(秒)」;单个渠道测试不会恢复渠道,手动禁用的渠道不会恢复。
- 定期测试间隔与页面不一致:部署环境可能设置了
CHANNEL_TEST_FREQUENCY或CHANNEL_TEST_ENABLED,它们会覆盖页面值;NODE_TYPE=slave的节点不执行定期测试。 - 找不到「清空该规则缓存」,或缓存列显示「不适用」:该规则没有开启「包含规则名」。
- 缓存条目一直是 0:使用 Redis 时容量显示
0属于正常。已用数一直为 0 时,依次检查:- 发送请求后是否点击了「刷新缓存」,缓存统计不会自动更新;
- 规则是否已通过页头「保存更改」提交,弹窗中的「保存」只更新草稿;
- 「启用会话保持」是否开启,规则的实际模式是否为「不保持」;
- 请求是否满足规则的全部条件,包括取到非空 Key 且通过 Value 正则;
- 请求是否被列表中前面的规则抢先命中,实际命中的规则名可在「请求策略决策」的「命中会话规则」一步中查看;
- 请求是否失败,失败的请求不写入绑定;
- 请求是否被固定到某个渠道,这类请求不经过会话规则。
- 保存时提示英文错误:这是后端校验返回的原文,本次提交的所有项都没有写入,修正后重新保存。
- 使用日志中看不到失败请求的决策记录:需要设置环境变量
ERROR_LOG_ENABLED=true。