refactor(guide): 重构指南页面为 Markdown 内容驱动架构

- 将各指南页面的内联硬编码内容抽取为独立 Markdown 文件
- 新增 MarkdownViewer 组件统一渲染 Markdown 内容
- 新增 ArchitectureDiagram 组件和架构演示组件
- 新增模块指南页面 (ModulesGuide)
- GuideLayout 支持子导航、页面过渡动画和图片 Lightbox
- guide-config 重构为支持 subItems 的导航结构
- 添加指南相关截图资源
This commit is contained in:
fawney19
2026-02-23 15:50:24 +08:00
parent c43d22b0e4
commit e18a7ee435
49 changed files with 2988 additions and 4735 deletions
+106 -586
View File
@@ -1,610 +1,130 @@
<script setup lang="ts">
import { RouterLink } from 'vue-router'
import {
ArrowRight,
TrendingUp,
Hash,
Info,
Activity
} from 'lucide-vue-next'
import { panelClasses } from './guide-config'
import { useSiteInfo } from '@/composables/useSiteInfo'
withDefaults(
defineProps<{
baseUrl?: string
}>(),
{
baseUrl: typeof window !== 'undefined' ? window.location.origin : 'https://your-aether.com'
}
)
const { siteName } = useSiteInfo()
// 调度模式
const schedulingModes = [
{
name: '提供商优先',
description: '按 Provider 优先级排序,同优先级内按 Key 优先级排序,相同优先级哈希分散。适合优先使用特定供应商。',
icon: TrendingUp,
badge: '默认'
},
{
name: '全局 Key 优先',
description: '忽略 Provider 层级,所有 Key 按全局优先级统一排序,相同优先级哈希分散。适合跨 Provider 统一调度,最大化利用所有 Key。',
icon: Hash,
badge: ''
}
]
// 错误分类
const errorCategories = [
{
type: 'RETRYABLE',
name: '可重试',
description: '超时、限流 (429)、5xx 服务端错误',
action: 'FailoverEngine 尝试下一个候选'
},
{
type: 'FATAL',
name: '致命',
description: '认证失败、模型不存在',
action: '立即返回错误,不再重试'
},
{
type: 'CLIENT',
name: '客户端',
description: '400 系列客户端错误',
action: '透传原始错误给调用方'
}
]
// 错误处理副作用
const errorSideEffects = [
{ name: '缓存失效', description: '通过 CacheAwareScheduler 失效亲和性缓存' },
{ name: '健康记录', description: '通过 health_monitor 记录失败事件' },
{ name: 'RPM 调整', description: '429 错误时自适应调整 RPM 限制' },
{ name: 'OAuth 标记', description: '403 VALIDATION_REQUIRED 时标记 Key 为账号封禁' }
]
// 格式转换三层开关
const conversionLayers = [
{
level: '全局',
setting: 'enable_format_conversion',
description: '系统设置中的全局开关。开启后允许所有跨格式路由。'
},
{
level: 'Provider',
setting: 'Provider.enable_format_conversion',
description: '全局关闭时,可在 Provider 级别单独开启格式转换。'
},
{
level: 'Endpoint',
setting: 'format_acceptance_config',
description: '以上两级都关闭时,通过端点的 accept/reject 规则精细控制接受哪些入站格式。'
}
]
// 配额类型
const quotaTypes = [
{
name: '请求次数配额',
description: '限制每日/每月的 API 调用次数,超过后请求会被拒绝',
scope: '用户级 / Key 级'
},
{
name: 'Token 用量配额',
description: '限制每日/每月的 Token 消耗量,适合控制成本',
scope: '用户级 / Key 级'
}
]
import { Target } from 'lucide-vue-next'
</script>
<template>
<div class="space-y-8">
<!-- 标题 -->
<div class="space-y-3">
<div class="space-y-12 pb-12">
<!-- Hero 区域 -->
<div class="space-y-4">
<div class="inline-flex items-center gap-1.5 rounded-full bg-[#cc785c]/10 dark:bg-[#cc785c]/20 border border-[#cc785c]/20 dark:border-[#cc785c]/40 px-3 py-1 text-xs font-medium text-[#cc785c] dark:text-[#d4a27f]">
<Target class="h-3 w-3" />
调度与策略
</div>
<h1 class="text-3xl font-bold text-[#262624] dark:text-[#f1ead8]">
关键策略
</h1>
<p class="text-base text-[#666663] dark:text-[#a3a094]">
{{ siteName }} 的调度、缓存亲和性、故障转移、并发控制等核心策略机制。
<p class="text-base text-[#666663] dark:text-[#a3a094] max-w-2xl">
了解 Aether 内部的日志记录、智能调度模式以及服务限制策略。
</p>
</div>
<!-- 调度策略 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
调度策略
</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
当一个模型关联了多个端点和密钥时,系统需要决定使用哪个 Provider + Endpoint + Key 组合。调度模式决定了候选的排序方式:
<section
id="request-logging"
class="scroll-mt-24 lg:scroll-mt-20"
>
<h2>1. 请求体记录</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094] mb-4">
在系统设置中,您可以修改请求体记录详情等级,以便于调试和审计。
</p>
<div class="grid gap-3 md:grid-cols-2">
<div
v-for="mode in schedulingModes"
:key="mode.name"
class="p-4"
:class="[panelClasses.section]"
>
<div class="flex items-center gap-2.5 mb-2">
<component
:is="mode.icon"
class="h-4 w-4 text-[#cc785c]"
/>
<h3 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8]">
{{ mode.name }}
</h3>
<span
v-if="mode.badge"
:class="panelClasses.badge"
>{{ mode.badge }}</span>
</div>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
{{ mode.description }}
</p>
</div>
</div>
<div
class="p-4"
:class="[panelClasses.section]"
>
<div class="flex items-start gap-3">
<Info class="h-4 w-4 text-blue-500 flex-shrink-0 mt-0.5" />
<div class="text-sm text-[#666663] dark:text-[#a3a094]">
<p class="font-medium text-[#262624] dark:text-[#f1ead8]">
哈希分散
</p>
<p class="mt-1">
当多个候选具有相同优先级时,系统使用哈希算法将请求均匀分散到各个候选上,避免所有请求集中到同一个 Key。
哈希因子结合了 affinity_key(通常为用户 API Key ID),使得同一用户的请求倾向于命中相同的候选。
</p>
</div>
</div>
</div>
</section>
<!-- 缓存亲和性 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
缓存亲和性
</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
缓存亲和性是 {{ siteName }} 的核心优化策略,用于最大化利用上游供应商的 Prompt Caching 机制。
</p>
<div
class="overflow-hidden"
:class="[panelClasses.section]"
>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.12)] bg-[#fafaf7]/50 dark:bg-[#1f1d1a]/50">
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094] w-10">
#
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
步骤
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
说明
</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.08)]">
<td class="px-4 py-2.5 text-[#cc785c] font-bold">
1
</td>
<td class="px-4 py-2.5 font-medium text-[#262624] dark:text-[#f1ead8] whitespace-nowrap">
提取亲和性键
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
用户发起请求时,系统提取 <code class="text-xs bg-[#f5f5f0] dark:bg-[#1f1d1a] px-1 py-0.5 rounded">affinity_key</code>(通常为用户 API Key ID)
</td>
</tr>
<tr class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.08)]">
<td class="px-4 py-2.5 text-[#cc785c] font-bold">
2
</td>
<td class="px-4 py-2.5 font-medium text-[#262624] dark:text-[#f1ead8] whitespace-nowrap">
查询缓存
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
查找该 affinity_key 上次成功使用的 ProviderAPIKey(从 Redis 缓存读取)
</td>
</tr>
<tr class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.08)]">
<td class="px-4 py-2.5 text-[#cc785c] font-bold">
3
</td>
<td class="px-4 py-2.5 font-medium text-[#262624] dark:text-[#f1ead8] whitespace-nowrap">
候选置顶
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
如果找到且该 Key 仍可用,将其置顶到候选列表最前面
</td>
</tr>
<tr class="last:border-0">
<td class="px-4 py-2.5 text-[#cc785c] font-bold">
4
</td>
<td class="px-4 py-2.5 font-medium text-[#262624] dark:text-[#f1ead8] whitespace-nowrap">
更新记录
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
请求成功后,更新缓存记录。请求失败时,失效该缓存条目
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="grid gap-3 md:grid-cols-2">
<div
class="p-4"
:class="[panelClasses.section]"
>
<h4 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8] mb-2">
为什么重要?
</h4>
<ul class="space-y-1 text-sm text-[#666663] dark:text-[#a3a094]">
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>Claude/OpenAI 等供应商支持 Prompt Caching,重复前缀可免费/降价</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>同一用户的连续请求通常有大量重复上下文</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>稳定路由到同一个 Key 可以最大化缓存命中率</span>
</li>
</ul>
</div>
<div
class="p-4"
:class="[panelClasses.section]"
>
<h4 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8] mb-2">
缓存层级
</h4>
<ul class="space-y-1 text-sm text-[#666663] dark:text-[#a3a094]">
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span><strong>L1 内存缓存</strong>:3 秒 TTL,减少 Redis 访问</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span><strong>L2 Redis 缓存</strong>:持久化亲和性映射</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span><strong>降级</strong>:Redis 不可用时禁用亲和性,使用普通排序</span>
</li>
</ul>
</div>
</div>
</section>
<!-- 故障转移 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
故障转移
</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
当某个候选失败时,系统会根据错误类型决定是否尝试下一个候选。错误分类由 ErrorClassifier 负责:
</p>
<div
class="overflow-hidden"
:class="[panelClasses.section]"
>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.12)] bg-[#fafaf7]/50 dark:bg-[#1f1d1a]/50">
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
类型
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
触发条件
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
处理方式
</th>
</tr>
</thead>
<tbody>
<tr
v-for="error in errorCategories"
:key="error.type"
class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.08)] last:border-0"
<div class="overflow-hidden rounded-xl border border-[#e5e4df] dark:border-[rgba(227,224,211,0.12)] bg-white dark:bg-[#191714] shadow-sm max-w-2xl">
<table class="w-full text-sm text-left">
<thead class="bg-[#f5f5f0] dark:bg-[rgba(227,224,211,0.05)] border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.12)]">
<tr>
<th
scope="col"
class="px-6 py-3 font-medium text-[#262624] dark:text-[#f1ead8]"
>
<td class="px-4 py-2.5 font-medium text-[#262624] dark:text-[#f1ead8] whitespace-nowrap">
<code class="text-xs bg-[#f5f5f0] dark:bg-[#1f1d1a] px-1.5 py-0.5 rounded">{{ error.type }}</code>
<span class="ml-1.5 text-[#666663] dark:text-[#a3a094] font-normal text-xs">{{ error.name }}</span>
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
{{ error.description }}
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
{{ error.action }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 错误处理副作用 -->
<div
class="p-4"
:class="[panelClasses.section]"
>
<h3 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8] mb-2">
错误处理副作用
</h3>
<p class="text-sm text-[#666663] dark:text-[#a3a094] mb-2.5">
错误分类后,ErrorHandlerService 负责执行副作用操作:
</p>
<div class="grid gap-2 sm:grid-cols-2">
<div
v-for="effect in errorSideEffects"
:key="effect.name"
class="p-3 rounded-lg bg-[#f5f5f0]/50 dark:bg-[#1f1d1a]/50"
>
<h4 class="font-medium text-xs text-[#262624] dark:text-[#f1ead8]">
{{ effect.name }}
</h4>
<p class="text-xs text-[#666663] dark:text-[#a3a094] mt-0.5">
{{ effect.description }}
</p>
</div>
</div>
</div>
</section>
<!-- 并发控制 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
并发控制
</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
系统通过多层并发控制保护上游服务不被过载:
</p>
<div class="grid gap-3 md:grid-cols-2">
<div
class="p-4"
:class="[panelClasses.section]"
>
<div class="flex items-center gap-2.5 mb-2">
<Activity class="h-4 w-4 text-[#cc785c]" />
<h3 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8]">
RPM 限流
</h3>
</div>
<ul class="space-y-1 text-sm text-[#666663] dark:text-[#a3a094]">
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>按 ProviderAPIKey 维度限制每分钟请求数</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>超过 RPM 限制的候选在构建阶段被跳过</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>429 错误时自适应降低 RPM 限制</span>
</li>
</ul>
</div>
<div
class="p-4"
:class="[panelClasses.section]"
>
<div class="flex items-center gap-2.5 mb-2">
<Activity class="h-4 w-4 text-[#cc785c]" />
<h3 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8]">
动态预留
</h3>
</div>
<ul class="space-y-1 text-sm text-[#666663] dark:text-[#a3a094]">
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>为缓存亲和性用户预留一定的 RPM 额度</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>避免非缓存用户占满配额导致缓存用户无法命中</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>预留比例根据负载情况自适应调整</span>
</li>
</ul>
</div>
</div>
</section>
<!-- 格式转换开关 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
格式转换控制
</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
格式转换(跨格式路由)由三层开关从高到低控制:
</p>
<div
class="overflow-hidden"
:class="[panelClasses.section]"
>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.12)] bg-[#fafaf7]/50 dark:bg-[#1f1d1a]/50">
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094] w-10">
#
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
层级
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
配置项
</th>
<th class="px-4 py-2.5 text-left font-medium text-[#666663] dark:text-[#a3a094]">
说明
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(layer, index) in conversionLayers"
:key="layer.level"
class="border-b border-[#e5e4df] dark:border-[rgba(227,224,211,0.08)] last:border-0"
日志等级
</th>
<th
scope="col"
class="px-6 py-3 font-medium text-[#262624] dark:text-[#f1ead8]"
>
<td class="px-4 py-2.5 text-[#cc785c] font-bold">
{{ index + 1 }}
</td>
<td class="px-4 py-2.5 font-medium text-[#262624] dark:text-[#f1ead8] whitespace-nowrap">
{{ layer.level }}
</td>
<td class="px-4 py-2.5 font-mono text-xs text-[#666663] dark:text-[#a3a094]">
{{ layer.setting }}
</td>
<td class="px-4 py-2.5 text-[#666663] dark:text-[#a3a094]">
{{ layer.description }}
</td>
</tr>
</tbody>
</table>
</div>
记录内容
</th>
</tr>
</thead>
<tbody class="divide-y divide-[#e5e4df] dark:divide-[rgba(227,224,211,0.06)]">
<tr class="hover:bg-black/5 dark:hover:bg-white/5 transition-colors">
<td class="px-6 py-4 font-mono font-medium text-[#cc785c] dark:text-[#d4a27f]">
Base
</td>
<td class="px-6 py-4 text-[#666663] dark:text-[#a3a094]">
基本请求信息(IP, 模型, 耗时, Token 等)
</td>
</tr>
<tr class="hover:bg-black/5 dark:hover:bg-white/5 transition-colors">
<td class="px-6 py-4 font-mono font-medium text-[#cc785c] dark:text-[#d4a27f]">
Headers
</td>
<td class="px-6 py-4 text-[#666663] dark:text-[#a3a094]">
Base + 请求头 (Headers)
</td>
</tr>
<tr class="hover:bg-black/5 dark:hover:bg-white/5 transition-colors border-b-0">
<td class="px-6 py-4 font-mono font-medium text-[#cc785c] dark:text-[#d4a27f]">
Full
</td>
<td class="px-6 py-4 text-[#666663] dark:text-[#a3a094]">
Headers + 完整的请求体与响应体 (Payloads)
</td>
</tr>
</tbody>
</table>
</div>
<div
class="p-4"
:class="[panelClasses.section]"
<img
loading="lazy"
src="/guide/strategy-request-logging.webp"
alt="请求体记录设置"
class="rounded-xl border border-[#e5e4df] dark:border-[rgba(227,224,211,0.12)] shadow-sm mt-6 w-full max-w-3xl"
>
<div class="flex items-start gap-3">
<Info class="h-4 w-4 text-blue-500 flex-shrink-0 mt-0.5" />
<div class="text-sm text-[#666663] dark:text-[#a3a094]">
<p class="font-medium text-[#262624] dark:text-[#f1ead8]">
优先级降级
</p>
<p class="mt-1">
需要格式转换的候选默认会被排到列表后面(降级排序)。通过全局 <code class="text-xs bg-[#f5f5f0] dark:bg-[#1f1d1a] px-1 py-0.5 rounded">keep_priority_on_conversion</code>
或 Provider 级别的同名配置,可以保持原有优先级不降级。
</p>
</div>
</div>
</div>
</section>
<!-- 配额管理 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
配额管理
</h2>
<div class="grid gap-3 md:grid-cols-2">
<div
v-for="quota in quotaTypes"
:key="quota.name"
class="p-4"
:class="[panelClasses.section]"
>
<h3 class="font-semibold text-sm text-[#262624] dark:text-[#f1ead8] mb-1.5">
{{ quota.name }}
</h3>
<p class="text-sm text-[#666663] dark:text-[#a3a094]">
{{ quota.description }}
</p>
<div class="mt-2">
<span :class="panelClasses.badgeBlue">{{ quota.scope }}</span>
</div>
</div>
</div>
<div
class="p-4"
:class="[panelClasses.section]"
>
<div class="flex items-start gap-3">
<Info class="h-4 w-4 text-blue-500 flex-shrink-0 mt-0.5" />
<div class="text-sm text-[#666663] dark:text-[#a3a094]">
<p class="font-medium text-[#262624] dark:text-[#f1ead8]">
配额继承
</p>
<p class="mt-1">
可以在用户级别设置默认配额,新创建的 API Key 会自动继承。也可以在创建 Key 时覆盖默认配额。
</p>
</div>
</div>
</div>
<section
id="scheduling"
class="scroll-mt-24 lg:scroll-mt-20"
>
<h2>2. 调度模式</h2>
<ul class="list-decimal pl-5 space-y-2 mt-4 text-[#666663] dark:text-[#a3a094] text-sm">
<li><strong class="text-[#262624] dark:text-[#f1ead8] font-medium">提供商优先:</strong> 优先根据提供商设置的顺序进行调度。</li>
<li><strong class="text-[#262624] dark:text-[#f1ead8] font-medium">Key优先:</strong> 无视提供商层级,直接在所有可用的 Key 之间根据优先级进行调度。</li>
<li><strong class="text-[#262624] dark:text-[#f1ead8] font-medium">缓存亲和:</strong> 尽量将相同用户的请求路由到之前处理过该用户请求的提供商/节点,以最大化利用上游缓存。</li>
<li><strong class="text-[#262624] dark:text-[#f1ead8] font-medium">负载均衡:</strong> 在相同优先级的节点之间均匀分配流量。</li>
<li><strong class="text-[#262624] dark:text-[#f1ead8] font-medium">固定顺序:</strong> 取消随机性与动态调整,严格按照固定的顺序遍历尝试。</li>
<li><strong class="text-[#262624] dark:text-[#f1ead8] font-medium">故障转移:</strong> 当请求失败时,根据策略自动切换到下一个可用的备用节点进行重试。</li>
</ul>
</section>
<!-- 健康监控 -->
<section class="space-y-3">
<h2 class="text-xl font-semibold text-[#262624] dark:text-[#f1ead8]">
健康监控
</h2>
<div
class="p-4"
:class="[panelClasses.section]"
>
<ul class="space-y-1.5 text-sm text-[#666663] dark:text-[#a3a094]">
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>系统持续记录每个端点的成功/失败请求</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>连续失败超过阈值的端点会被标记为不健康</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>不健康的端点在候选构建时被跳过,请求自动路由到其他端点</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>定期对不健康端点进行探测恢复</span>
</li>
<li class="flex items-start gap-2">
<span class="text-[#cc785c] mt-1.5 flex-shrink-0 text-[6px]">&#9679;</span>
<span>可以在管理后台的「健康监控」页面查看实时状态并手动触发检查</span>
</li>
</ul>
</div>
<section
id="rate-limit"
class="scroll-mt-24 lg:scroll-mt-20"
>
<h2>3. 访问限制</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094] mb-4">
系统支持多种维度的访问频率限制(Rate Limit),有效防止恶意请求或滥用,保障服务稳定性。
</p>
</section>
<!-- 下一步 -->
<section class="pt-2">
<RouterLink
to="/guide/advanced"
class="p-4 flex items-center gap-3 group"
:class="[panelClasses.section, panelClasses.cardHover]"
>
<div class="flex-1">
<div class="font-medium text-sm text-[#262624] dark:text-[#f1ead8]">
下一步:高级功能
</div>
<div class="text-xs text-[#666663] dark:text-[#a3a094]">
格式转换操作、请求头/请求体规则、系统设置
</div>
</div>
<ArrowRight class="h-4 w-4 text-[#999] group-hover:text-[#cc785c] transition-colors" />
</RouterLink>
<section
id="payload-cleanup"
class="scroll-mt-24 lg:scroll-mt-20"
>
<h2>4. 请求体压缩清理</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094] mb-4">
为节省数据库空间与提高查询性能,系统提供自动请求体清理与压缩策略,将历史请求详情定期冷热分离并清理。
</p>
</section>
<section
id="cron-tasks"
class="scroll-mt-24 lg:scroll-mt-20"
>
<h2>5. 定时任务</h2>
<p class="text-sm text-[#666663] dark:text-[#a3a094] mb-4">
平台内置多个定时任务,用于模型列表同步、缓存清理、余额监控及统计数据聚合等周期性操作。
</p>
</section>
</div>
</template>