系统设置
系统配置管理
系统配置管理
Claude Code Hub 采用了分层配置架构,将基础设施关注点与业务逻辑分离。系统使用环境变量处理特定于部署的设置,并使用数据库持久化处理动态运行时配置,让您能够灵活地调整行为而无需重启服务。
配置架构概览
配置系统分为三个截然不同的层:
运行时层 (内存缓存)
├── 系统设置缓存 (60s TTL)
├── 熔断器状态
└── 动态日志级别
数据库层 (PostgreSQL)
├── system_settings (全局配置)
├── providers (供应商设置)
└── users/keys (配额与限制)
环境层 (process.env)
├── 数据库连接
├── Redis 配置
└── 安全策略
这种分层方法具有以下优势:
- 类型安全:所有配置在编译和运行时都使用 Zod 模式进行验证
- 故障开放弹性:Redis 等关键依赖具有自动回退机制
- 热重载:数据库持久化设置的更新无需重启服务
- 验证保证:强制执行架构验证,防止无效配置进入生产环境
环境变量配置
环境变量处理基础设施层面的配置。这些变量在 src/lib/config/env.schema.ts 中定义,并在首次访问时使用 Zod 进行验证。
布尔值处理
系统使用自定义的布尔转换器来处理常见的 JavaScript 陷阱,即 Boolean("false") === true:
const booleanTransform = (s: string) => s !== "false" && s !== "0";
只有字符串 "false" 和 "0" 会被评估为 false。所有其他值,包括 "true"、"1" 或任何非空字符串,都会被评估为 true。
延迟验证模式
配置验证采用单例模式和延迟初始化,以避免在构建阶段触发验证:
let _envConfig: EnvConfig | null = null;
export function getEnvConfig(): EnvConfig {
if (!_envConfig) {
_envConfig = EnvSchema.parse(process.env);
}
return _envConfig;
}
这确保了即使在尚未配置环境变量的情况下,Next.js 构建也能成功完成。
核心环境变量
基础应用设置
| 变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|
NODE_ENV | enum | development | 运行时环境:development、production 或 test |
PORT | number | 23000 | 应用监听端口 |
TZ | string | Asia/Shanghai | 用于时间边界计算的系统时区 |
数据库配置
DSN 变量接受 PostgreSQL 连接 URL。该架构包含占位符检测,以防止构建失败:
DSN: z.preprocess((val) => {
if (!val || typeof val !== "string") return undefined;
if (val.includes("user:password@host:port")) return undefined;
return val;
}, z.string().url().optional())
多副本部署的连接池设置:
| 变量 | 范围 | 默认值 | 描述 |
|---|---|---|---|
DB_POOL_MAX | 1-200 | 20 (prod) / 10 (dev) | 每个进程的最大连接数 |
DB_POOL_IDLE_TIMEOUT | 0-3600s | 20 | 空闲连接回收时间 |
DB_POOL_CONNECT_TIMEOUT | 1-120s | 10 | 建立连接超时时间 |
在部署到具有多个副本的 Kubernetes 时,请根据数据库的 max_connections 设置除以预期副本数来计算 DB_POOL_MAX。
消息请求写入模式
MESSAGE_REQUEST_WRITE_MODE 变量控制请求日志的写入方式:
async(默认):缓冲写入并定期刷新,在高流量期间减轻数据库负载sync:立即写入,与旧版本行为兼容,但会增加请求延迟
异步模式调优参数:
| 变量 | 范围 | 默认值 | 描述 |
|---|---|---|---|
MESSAGE_REQUEST_ASYNC_FLUSH_INTERVAL_MS | 10-60000 | 250 | 刷新间隔(毫秒) |
MESSAGE_REQUEST_ASYNC_BATCH_SIZE | 1-2000 | 200 | 每次批量写入的记录数 |
MESSAGE_REQUEST_ASYNC_MAX_PENDING | 100-200000 | 5000 | 最大队列记录数 |
安全配置
ADMIN_TOKEN 变量支持占位符检测,以实现安全的部署实践:
ADMIN_TOKEN: z.preprocess((val) => {
if (!val || typeof val !== "string") return undefined;
if (val === "change-me") return undefined;
return val;
}, z.string().min(1).optional())
Cookie 安全性由 ENABLE_SECURE_COOKIES 控制:
true(默认):在 Cookie 上设置Secure标志,除 localhost 外均要求 HTTPSfalse:允许在内网部署中使用 HTTP 传输 Cookie
Redis 与限流
| 变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|
REDIS_URL | string | 可选 | Redis 连接 URL,支持用于 TLS 的 rediss:// |
REDIS_TLS_REJECT_UNAUTHORIZED | boolean | true | 验证 TLS 证书 |
ENABLE_RATE_LIMIT | boolean | true | 启用限流功能 |
系统实现了故障开放(Fail-Open)策略:如果 Redis 不可用,限流和会话统计将自动优雅降级,而不会阻塞请求。
会话配置:
| 变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|
SESSION_TTL | number | 300 | 会话过期时间(秒) |
STORE_SESSION_MESSAGES | boolean | false | 在 Redis 中存储原始消息内容 |
将 STORE_SESSION_MESSAGES 设置为 true 会存储完整的请求和响应体。默认值 false 会存储元数据,但会将消息内容脱敏为 [REDACTED],以保护隐私并减少存储占用。
熔断器配置
ENABLE_CIRCUIT_BREAKER_ON_NETWORK_ERRORS 控制哪些错误会计入熔断器阈值:
false(默认):仅供应商错误(HTTP 4xx/5xx 响应)增加失败计数true:所有错误(包括网络超时和 DNS 故障)均增加失败计数
在网络连接不稳定的环境中请使用 false,以防止临时问题触发熔断器。
供应商缓存
ENABLE_PROVIDER_CACHE 控制供应商配置的进程级缓存:
true(默认):启用 30 秒 TTL 缓存,并使用 Redis Pub/Sub 进行跨实例失效false:禁用缓存,每次请求都查询数据库
重试与超时配置
最大重试次数:
MAX_RETRY_ATTEMPTS_DEFAULT: z.coerce.number().min(1).max(10).default(2)
Fetch 超时设置(毫秒):
| 变量 | 默认值 | 描述 |
|---|---|---|
FETCH_CONNECT_TIMEOUT | 30000 | TCP 建立连接超时时间 |
FETCH_HEADERS_TIMEOUT | 600000 | 接收响应头超时时间 |
FETCH_BODY_TIMEOUT | 600000 | 请求/响应体传输超时时间 |
调低 FETCH_CONNECT_TIMEOUT 可以更快报错并切换到备用供应商。对于冷启动延迟较高的模型,可以调高 FETCH_HEADERS_TIMEOUT。
日志配置
| 变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|
LOG_LEVEL | enum | info | 日志输出详细程度 |
DEBUG_MODE | boolean | false | 旧版调试标志 |
日志级别从最详细到最简略的层次结构为:trace > debug > info > warn > error > fatal
可以通过 /api/admin/log-level API 动态调整日志级别,而无需重启服务。
数据库迁移
AUTO_MIGRATE 控制是否在启动时自动运行 Drizzle 迁移:
true(默认):自动应用待处理的迁移false:需要手动执行迁移
对于生产环境,可以考虑在初始部署后设置为 false,以控制模式更改的应用时机。
数据库持久化配置
存储在 PostgreSQL 中的设置可以通过管理界面在运行时进行修改。这些设置在内存中缓存,TTL 为 60 秒,以平衡新鲜度与性能。
系统设置表
system_settings 表存储全局配置选项。如果记录不存在,系统将使用合理的默认值创建一条记录。
基础设置
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
siteTitle | varchar(128) | "Claude Code Hub" | 界面中显示的站点标题 |
allowGlobalUsageView | boolean | false | 允许非管理员用户查看全局使用统计信息 |
currencyDisplay | varchar(10) | "USD" | 成本显示的货币单位 |
billingModelSource | varchar(20) | "original" | 成本计算方法:original(原始)或 redirected(重定向) |
timezone | varchar(64) | null | 系统时区 (IANA 标识符) |
日志清理配置
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
enableAutoCleanup | boolean | false | 启用自动日志清理 |
cleanupRetentionDays | integer | 30 | 日志保留天数 |
cleanupSchedule | varchar(50) | "0 2 * * *" | Cron 格式的清理计划 |
cleanupBatchSize | integer | 10000 | 每批次删除的记录数 |
协议与代理设置
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
enableHttp2 | boolean | false | 连接供应商时使用 HTTP/2 |
enableClientVersionCheck | boolean | false | 强制执行最低客户端版本要求 |
verboseProviderError | boolean | false | 供应商故障时返回详细的错误信息 |
interceptAnthropicWarmupRequests | boolean | false | 特殊拦截并处理 Anthropic 预热请求 |
响应修复配置
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
enableThinkingSignatureRectifier | boolean | true | 修复 Anthropic 供应商的思维签名(Thinking Signature)不兼容问题 |
enableCodexSessionIdCompletion | boolean | true | 自动补全缺失的 Codex 会话 ID |
enableResponseFixer | boolean | true | 启用响应内容修复 |
responseFixerConfig | jsonb | 见下文 | 详细的响应修复器设置 |
responseFixerConfig JSON 结构:
{
fixTruncatedJson: true, // 修复不完整的 JSON 响应
fixSseFormat: true, // 修复 Server-Sent Events 格式问题
fixEncoding: true, // 纠正字符编码问题
maxJsonDepth: 200, // 最大 JSON 解析深度
maxFixSize: 1024 * 1024 // 处理的最大响应大小 (1MB)
}
配额租赁配置
配额租赁控制在多副本部署中如何在实例之间分配使用限制:
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
quotaDbRefreshIntervalSeconds | integer | 10 | 从数据库刷新配额数据的频率 |
quotaLeasePercent5h | numeric | 0.05 | 5 小时限制租赁百分比 (5%) |
quotaLeasePercentDaily | numeric | 0.05 | 每日限制租赁百分比 (5%) |
quotaLeasePercentWeekly | numeric | 0.05 | 每周限制租赁百分比 (5%) |
quotaLeasePercentMonthly | numeric | 0.05 | 每月限制租赁百分比 (5%) |
quotaLeaseCapUsd | numeric | null | 最大租赁金额(美元) |
系统设置缓存
为了避免在每个代理请求中都进行数据库查询,系统维护了一个内存缓存,具有以下特点:
- TTL:60 秒
- 延迟加载:过期后在首次访问时从数据库获取
- 手动失效:更新设置时立即清除
- 故障开放:如果数据库不可用,返回默认值
数据库无法访问时的默认回退值:
const DEFAULT_SETTINGS = {
enableHttp2: false,
interceptAnthropicWarmupRequests: false,
enableThinkingSignatureRectifier: true,
enableCodexSessionIdCompletion: true,
enableResponseFixer: true,
responseFixerConfig: {
fixTruncatedJson: true,
fixSseFormat: true,
fixEncoding: true,
maxJsonDepth: 200,
maxFixSize: 1024 * 1024,
},
};
供应商配置
供应商特定的设置存储在 providers 表中,包括:
路由配置
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
weight | integer | 1 | 路由权重 (1-100) |
priority | integer | 0 | 选择优先级(值越高越优先) |
costMultiplier | numeric | 1.0 | 账单计算的成本乘数 |
groupTag | varchar(50) | null | 供应商分组标签 |
熔断器设置
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
maxRetryAttempts | integer | null | 覆盖全局重试次数(null 表示使用默认值) |
circuitBreakerFailureThreshold | integer | 5 | 开启熔断器前的失败次数 |
circuitBreakerOpenDuration | integer | 1800000 | 保持开启状态的毫秒数(30 分钟) |
circuitBreakerHalfOpenSuccessThreshold | integer | 2 | 关闭熔断器所需的成功次数 |
网络配置
| 字段 | 类型 | 描述 |
|---|---|---|
proxyUrl | varchar(512) | HTTP/HTTPS/SOCKS5 代理地址 |
proxyFallbackToDirect | boolean | 代理失败时允许直接连接 |
超时配置
| 字段 | 类型 | 描述 |
|---|---|---|
firstByteTimeoutStreamingMs | integer | 流式响应首字节超时 |
streamingIdleTimeoutMs | integer | 流式连接空闲超时 |
requestTimeoutNonStreamingMs | integer | 非流式请求的总超时 |
用户与 Key 配置
用户级限制
| 字段 | 类型 | 描述 |
|---|---|---|
rpmLimit | integer | 每分钟请求数 (RPM) 限制 |
dailyLimitUsd | numeric | 每日限额(美元) |
providerGroup | varchar(200) | 分配的供应商组 |
tags | jsonb | 用户标签数组 |
allowedClients | jsonb | 允许的客户端模式 |
allowedModels | jsonb | 允许的模型列表 |
Key 级限制
| 字段 | 类型 | 描述 |
|---|---|---|
limit5hUsd | numeric | 5 小时限额 |
limitDailyUsd | numeric | 每日限额 |
dailyResetMode | enum | 重置模式:fixed(固定时间)或 rolling(24 小时滚动窗口) |
dailyResetTime | varchar(5) | 固定模式的重置时间 (HH:mm 格式) |
limitWeeklyUsd | numeric | 每周限额 |
limitMonthlyUsd | numeric | 每月限额 |
limitTotalUsd | numeric | 总限额 |
limitConcurrentSessions | integer | 最大并发会话数 |
cacheTtlPreference | varchar(10) | 覆盖缓存 TTL 偏好 |
配置验证
所有配置更新都通过 src/lib/validation/schemas.ts 中定义的 Zod 模式进行验证。
系统设置验证
export const UpdateSystemSettingsSchema = z.object({
siteTitle: z.string().min(1).max(128).optional(),
allowGlobalUsageView: z.boolean().optional(),
currencyDisplay: z.enum(Object.keys(CURRENCY_CONFIG)).optional(),
billingModelSource: z.enum(["original", "redirected"]).optional(),
timezone: z.string().refine(isValidIANATimezone).optional(),
// ... 其他字段
});
时区验证
时区根据 IANA 时区数据库进行验证:
export function isValidIANATimezone(timezone: string): boolean {
try {
Intl.DateTimeFormat(undefined, { timeZone: timezone });
return true;
} catch {
return false;
}
}
供应商模式验证
供应商配置包含全面的验证:
export const CreateProviderSchema = z.object({
name: z.string().min(1).max(64),
url: z.string().url().max(255),
key: z.string().min(1).max(1024),
weight: z.number().int().min(1).max(100).default(1),
priority: z.number().int().min(0).max(2147483647).default(0),
cost_multiplier: z.number().min(0).default(1.0),
circuit_breaker_failure_threshold: z.number().int().min(0).optional(),
circuit_breaker_open_duration: z.number().int().min(1000).max(86400000).optional(),
circuit_breaker_half_open_success_threshold: z.number().int().min(1).max(10).optional(),
proxy_url: z.string().max(512).nullable().optional(),
proxy_fallback_to_direct: z.boolean().default(false),
});
限制常量
验证限制被集中管理以便于维护:
export const PROVIDER_LIMITS = {
WEIGHT: { MIN: 1, MAX: 100 },
MAX_RETRY_ATTEMPTS: { MIN: 1, MAX: 10 },
LIMIT_5H_USD: { MIN: 0.1, MAX: 1000, STEP: 1 },
LIMIT_WEEKLY_USD: { MIN: 1, MAX: 5000, STEP: 1 },
LIMIT_MONTHLY_USD: { MIN: 10, MAX: 30000, STEP: 1 },
CONCURRENT_SESSIONS: { MIN: 1, MAX: 150 },
} as const;
运行时配置更新
系统设置更新流程
当您通过管理界面修改设置时,会发生以下过程:
- 表单提交:从设置表单中收集更改
- 模式验证:
UpdateSystemSettingsSchema验证所有输入 - 数据库更新:
updateSystemSettings()将更改持久化到 PostgreSQL - 缓存失效:
invalidateSystemSettingsCache()清除内存缓存 - 路径重新验证:
revalidatePath()刷新 Next.js 静态生成
export async function saveSystemSettings(formData: {...}) {
const validated = UpdateSystemSettingsSchema.parse(formData);
const updated = await updateSystemSettings(validated);
invalidateSystemSettingsCache();
for (const locale of locales) {
revalidatePath(`/${locale}/settings/config`);
revalidatePath(`/${locale}/dashboard`);
}
return { ok: true, data: updated };
}
动态日志级别调整
日志级别可以在运行时通过 API 更改:
export async function POST(req: Request) {
const { level } = await req.json();
setLogLevel(level as LogLevel);
return Response.json({ success: true, level });
}
更改会立即对所有随后的日志输出生效。
时区解析
系统通过级联回退来解析时区:
数据库时区 -> 环境 TZ -> UTC
- 首先检查
system_settings.timezone - 如果为 null,则使用
TZ环境变量 - 如果未定义,则默认为 UTC
这允许根据部署情况定制时区,同时保持合理的默认值。
配置最佳实践
生产部署清单
生产环境所需的关键环境变量:
# 安全性 (务必更改默认值!)
ADMIN_TOKEN=your-secure-random-token
# 数据库连接
DSN=postgresql://user:password@postgres:5432/db_name
# 用于缓存和限流的 Redis
REDIS_URL=redis://redis:6379
# 您所在地区的时区
TZ=Asia/Shanghai
# 初始设置后禁用自动迁移
AUTO_MIGRATE=false
性能调优
对于高流量部署:
# 增加连接池(根据数据库 max_connections 进行调整)
DB_POOL_MAX=50
# 启用异步写入以减轻数据库负载
MESSAGE_REQUEST_WRITE_MODE=async
MESSAGE_REQUEST_ASYNC_BATCH_SIZE=500
# 启用供应商缓存
ENABLE_PROVIDER_CACHE=true
对于网络环境不稳定的情况:
# 增加连接超时
FETCH_CONNECT_TIMEOUT=60000
# 在网络错误时不启用熔断器
ENABLE_CIRCUIT_BREAKER_ON_NETWORK_ERRORS=false
# 增加重试次数
MAX_RETRY_ATTEMPTS_DEFAULT=3
监控配置
# 生产环境日志级别
LOG_LEVEL=info
# 启用详细的供应商错误以便调试(通过 UI 设置)
# verboseProviderError: true
# 启用自动日志清理(通过 UI 设置)
# enableAutoCleanup: true
# cleanupRetentionDays: 7
总结
Claude Code Hub 的配置系统提供了:
- 清晰的分离:环境变量用于基础设施,数据库用于业务逻辑,内存用于运行时优化
- 类型安全:从输入到存储的全程 Zod 验证
- 高可用性:故障开放策略确保在依赖项故障期间服务连续性
- 运维灵活性:热重载能力最大限度地减少服务中断
- 向后兼容性:合理的默认值和优雅降级支持无缝升级
模块化设计允许组件独立演进,同时保持系统一致性和可靠性。通过仔细的缓存和验证策略,系统在性能、准确性和安全性之间取得了平衡。
