cc-switch 本地代理服务实战指南:监听配置、应用接管与 API 格式转换原理
cc-switch 的本地代理服务在 127.0.0.1:15721 上启动一个 HTTP 代理,将 Claude、Codex、Gemini 等应用的 API 请求统一经其转发,从而实现请求日志记录、用量统计与供应商故障转移(Failover)。本文以官方用户手册中的代理服务文档为主体,结合 代理服务器实现、代理服务业务层 与 代理类型定义,讲清楚服务的启动/停止方式、监听配置、运行状态指标、应用接管的底层机制、API 格式转换与常见问题排查。
一、功能定位:为什么需要本地代理
本地代理服务(Proxy Service)是 cc-switch 将"配置管理"升级为"流量治理"的核心组件,主要用途包括:
- 记录请求日志:为每个 API 请求落一条结构化日志;
- 统计 API 用量:聚合 Token 消耗与请求耗时,支撑用量面板;
- 支持故障转移:当前供应商连续失败时自动切换到队列中的下一家;
- 统一管理多应用请求:Claude、Codex、Gemini 等应用共用一个本地入口,由 ProviderRouter 按应用类型路由到对应供应商。
从源码结构看,代理服务器基于 Axum 构建,并使用手动 hyper HTTP/1.1 accept 循环以 preserve_header_case(true) 保留客户端原始请求头的大小写,保证转发到上游时的线级头部与"不走代理直连"完全一致(见 server.rs 文件头注释)。
二、启动代理的两种方式
方式 1:主界面开关
点击主界面顶部的代理服务开关按钮即可启动。开关颜色表示状态:
- 白色:代理已停止;
- 绿色:代理运行中。
对应前端组件为 ProxyToggle,状态轮询由 useProxyStatus 驱动。
方式 2:设置页
- 打开"设置 → 高级 → 代理服务";
- 点击面板右上角的开关。
该面板由 ProxyTabContent 渲染,内部再组合 ProxyPanel 显示运行指标。
三、基本配置项与默认值
官方文档列出的核心配置
| 配置项 | 说明 | 默认值 |
|---|---|---|
| 监听地址 | 代理绑定的 IP 地址 | 127.0.0.1 |
| 监听端口 | 代理监听的端口 | 15721 |
| 启用日志 | 是否记录请求日志 | 开启 |
这些默认值在后端 ProxyConfig 的 Default 实现 中可以直接验证:
impl Default for ProxyConfig {
fn default() -> Self {
Self {
listen_address: "127.0.0.1".to_string(),
listen_port: 15721, // 使用较少占用的高位端口
max_retries: 3,
request_timeout: 600,
enable_logging: true,
live_takeover_active: false,
streaming_first_byte_timeout: 60,
streaming_idle_timeout: 120,
non_streaming_timeout: 600,
}
}
}
数据库层同样将 15721 作为 schema 默认值持久化(见 proxy_config 表定义:listen_port INTEGER NOT NULL DEFAULT 15721),配置在应用重启后依然生效。
源码中更多可配置的超时参数
除了文档表格中的三项,ProxyConfig 结构体 还包含一组面向长请求的超时参数,对大模型流式场景很关键:
| 字段 | 含义 | 默认值 |
|---|---|---|
max_retries |
最大重试次数 | 3 |
streaming_first_byte_timeout |
流式首字超时(1–120 秒) | 60 秒 |
streaming_idle_timeout |
流式静默超时,两个数据块间的最大间隔(60–600 秒,填 0 禁用) | 120 秒 |
non_streaming_timeout |
非流式请求总超时(60–1200 秒) | 600 秒 |
这些参数解释了"请求超时"类故障的排查方向:如果模型思考时间较长但网络正常,往往是流式静默超时先于上游触发。
修改配置的步骤
- 先停止代理服务(修改地址/端口前必须停止);
- 修改监听地址或端口;
- 点击"保存";
- 重新启动代理。
注意:地址/端口变更需要先停止服务,因为监听器只在启动时绑定一次。从 ProxyServer::start 的实现看,启动流程是解析
listen_address:listen_port为SocketAddr,随后调用tokio::net::TcpListener::bind;绑定失败会返回ProxyError::BindFailed——这就是 FAQ 中 "Address already in use" 报错的来源。
监听地址说明
| 地址 | 说明 |
|---|---|
127.0.0.1 |
仅本机可访问(推荐) |
0.0.0.0 |
允许局域网内其他设备访问 |
由于代理转发的是带真实凭据的 API 流量,源码中的 HTTP 客户端也对"代理是否指向回环地址"做了专门校验(见 http_client.rs 中的 proxy_points_to_loopback 测试),这从实现侧印证了文档"仅本机访问推荐"的建议。
四、运行状态面板
代理运行中,面板显示以下四类信息。
4.1 服务地址
http://127.0.0.1:15721
面板提供"复制"按钮一键复制该地址。这个地址就是后续接管各应用时写入的 base_url。
4.2 当前使用供应商
按应用显示当前路由目标:
Claude: PackyCode
Codex: AIGoCode
Gemini: Google 官方
底层对应 ProxyStatus 中的 current_provider 字段与 active_targets 列表(每个 ActiveTarget 记录 app_type / provider_name / provider_id)。
4.3 统计数据
| 指标 | 说明 |
|---|---|
| 活跃连接数 | 当前正在处理的请求数 |
| 总请求数 | 启动以来的累计请求数 |
| 成功率 | 成功请求占比(>90% 显示绿色,≤90% 显示黄色) |
| 运行时长 | 代理持续运行时间 |
这些指标与 ProxyStatus 结构体 的字段一一对应:active_connections、total_requests、success_rate、uptime_seconds,另有 last_error、failover_count 等字段供前端展示最近的错误与切换次数。
4.4 故障转移队列
代理面板按应用类型显示 Failover 队列,前端由 FailoverQueueManager 渲染:
Claude
├── 1. PackyCode [使用中] ●
├── 2. AIGoCode ●
└── 3. 备用 ○
Codex
├── 1. AIGoCode [使用中] ●
└── 2. 备用 ●
队列元素含义:
- 数字表示优先级顺序;
- "使用中"标签标记当前正在服务的供应商;
- 健康徽标反映供应商状态:
- 绿色:健康(连续失败 0 次);
- 黄色:降级(连续失败 1–2 次);
- 红色:不健康(连续失败 ≥3 次)。
该徽标逻辑对应 ProviderHealthBadge,其数据源是 ProviderHealth 结构中的 consecutive_failures(连续失败计数)与 is_healthy 布尔值;熔断判断本身由 ProviderRouter 持有并在跨请求间保持状态(见 ProxyState 注释:"共享的 ProviderRouter(持有熔断器状态,跨请求保持)")。
五、工作原理
5.1 请求流转
sequenceDiagram
participant CLI as CLI 工具 (Claude)
participant Proxy as 本地代理 (CC Switch)
participant API as API 供应商 (Anthropic)
participant DB as 数据存储 (Logger)
CLI->>Proxy: 发送 API 请求
Proxy->>DB: 记录请求日志/统计用量
Proxy->>API: 转发请求
API-->>Proxy: 返回响应
Proxy-->>CLI: 返回响应
5.2 应用接管:配置改写机制
代理启动并启用应用接管后,cc-switch 会改写各应用的本地配置,把流量指向本地代理:
Claude(settings.json 的 env):
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:15721"
}
}
Codex(config.toml):
base_url = "http://127.0.0.1:15721/v1"
Gemini(环境变量):
GOOGLE_GEMINI_BASE_URL=http://127.0.0.1:15721
源码层面有几个值得注意的实现细节:
- 占位 Token:接管模式下,写回 Live 配置的 API Key 使用占位符
PROXY_MANAGED,避免客户端因"缺少 key"报错,同时不泄露真实 Token(见 PROXY_TOKEN_PLACEHOLDER 常量)。 - 接管状态按应用独立跟踪:ProxyTakeoverStatus 为
claude、codex、gemini、grokbuild、opencode、openclaw各维护一个布尔位,说明接管是逐应用粒度的,可以只接管部分应用。 - 模型覆盖字段的接管:接管 Claude 时,
ANTHROPIC_MODEL等 12 个模型覆盖字段会被移除并改写成稳定的 Claude 角色别名(haiku/sonnet/opus/fable),再由本地代理映射到当前供应商的真实模型,防止模型菜单残留上一家供应商的名称(见 CLAUDE_MODEL_OVERRIDE_ENV_KEYS 及其注释)。 - 接管前的配置快照:写入新配置之前,原始 Live 配置会作为
LiveBackup(含app_type与original_config,见 LiveBackup 结构)备份到数据库,供停止时精确恢复。
六、API 格式转换
代理对设置了非 Anthropic 格式供应商的场景支持自动 API 格式转换,使仅支持 OpenAI 兼容 API 的供应商也能被 Claude Code 使用:
| 供应商 API 格式 | 代理行为 |
|---|---|
| Anthropic Messages | 直通(不转换) |
| OpenAI Chat Completions | Anthropic 请求转换为 OpenAI Chat 格式,响应再逆转换 |
| OpenAI Responses API | Anthropic 请求转换为 OpenAI Responses 格式,响应再逆转换 |
API 格式在添加/编辑 Claude 供应商时的"高级选项"中按供应商配置(参见添加供应商文档的 API 格式一节)。转换的入口实现在 forwarder.rs 与 providers 模块 中,按供应商配置的 api_format 分派不同转换管道。
注意:格式转换依赖代理处于"应用接管启用"的运行状态;转换同时覆盖流式与非流式两类请求。
七、停止代理与恢复行为
停止方式
- 方式 1:点击主界面开关关闭代理;
- 方式 2:在代理面板中将开关设为关闭。
停止时的三步处理
代理停止时,cc-switch 依次执行:
- 恢复应用配置:把各应用配置写回接管前的原始状态;
- 保存请求日志:将本轮运行的请求记录落库;
- 关闭所有连接:终止监听并释放端口。
从源码看,停止走的是带恢复语义的 stop_with_restore 路径(services/proxy.rs),内部先停服务、再对每个被接管的应用执行 restore_live_config_for_app 系列函数,用 LiveBackup 中保存的原始配置覆盖回写。该模块还针对 Codex 的 auth.json 实现了带硬链接探针的事务式恢复(CodexAuthFileTransaction),保证"恢复配置"和"用户正在 Codex 内重新登录"两个并发操作不会互相覆盖;仓库中 stop_with_restore*、restore_* 相关的测试用例(同一文件内 restore_waits_for_hot_switch_and_restores_latest_backup 等十余个测试)覆盖了这些边界场景。
八、请求日志
启用日志
打开代理面板的"启用日志"开关(对应 ProxyConfig.enable_logging,默认开启)。
日志字段
每条请求记录包含:
| 字段 | 说明 |
|---|---|
| 时间 | 请求发生时间 |
| 应用 | Claude / Codex / Gemini |
| 供应商 | 实际使用的供应商 |
| 模型 | 请求的模型名 |
| Token | 输入/输出 Token 数 |
| 延迟 | 请求耗时 |
| 状态 | 成功/失败 |
查看日志
在"设置 → 用量"标签页中查看请求日志,前端实现见 RequestLogTable。
九、常见问题排查
9.1 端口被占用
错误信息:Address already in use。
解决方法:
- 更换端口(例如 5001);
- 或结束占用该端口的程序。
对应源码中 TcpListener::bind 失败即抛出 BindFailed(server.rs 启动流程),因此该报错只会在启动/重启阶段出现。
9.2 代理启动失败
检查清单:
- 端口是否被其他程序占用;
- 是否有足够权限(部分系统对低端口段有限制);
- 防火墙是否拦截了本地回环连接。
9.3 请求超时
可能原因:
- 网络问题;
- 供应商服务端问题;
- 代理配置错误。
排查手段:
- 确认网络连通性;
- 绕过代理直接访问供应商 API 验证账号/Key 是否有效;
- 核对供应商配置(尤其是
base_url与 API 格式设置),并留意流式/非流式超时参数是否过短。
十、延伸阅读
- 相关实现:代理服务器、代理服务层、代理类型定义、供应商路由器;
- 前端面板:ProxyPanel、FailoverQueueManager、ProxyTabContent;
- 同系列文档:4.2 路由、4.3 故障转移、4.4 用量。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

