独家合作CubenceAI 中转平台立减 10%访问

系统设置

自动清理

自动清理

作为一个处理大量请求的 AI API 代理平台,Claude Code Hub 会产生大量的日志数据、临时文件和缓存信息。如果没有适当的清理机制,这些数据会无限累积,导致存储耗尽、性能下降和运营成本增加。

自动清理系统为跨多种数据类型的管理数据保留提供了一个全面的、生产级的解决方案。它通过可配置的策略和自动化调度处理消息请求日志、端点探测日志、临时文件和内存缓存。

为什么自动清理很重要

如果没有自动化清理,您的部署将面临几个风险:

存储耗尽message_request 表存储了每个 API 请求的详细记录。在高流量环境中,该表每天可能增长数百万行,最终消耗所有可用的数据库存储。

性能下降。大表会减慢查询速度,增加备份时间,并使数据库维护操作更具破坏性。随着表大小的增长,索引的效率会降低。

成本膨胀。云存储成本随数据量线性增加。保留日志的时间超过必要长度会直接影响您的基础设施预算。

合规风险。许多数据隐私法规要求在特定的保留期后删除个人数据。保留日志超过必要期限可能违反这些要求。

自动清理系统通过多种互补机制协同工作,解决这些问题,确保您的部署保持精简和高效。

清理机制概览

Claude Code Hub 实现了四种不同的清理机制,每种机制针对特定类型的数据:

机制目标数据调度配置
消息请求清理message_request 表中的 API 请求日志基于 Cron,通过 Bull 队列数据库设置
端点探测日志清理健康检查日志24 小时间隔环境变量
临时文件清理数据库备份/恢复临时文件1 小时间隔硬编码默认值
缓存清理内存会话和供应商缓存60 秒间隔硬编码默认值

每种机制独立运行,允许您根据特定要求调整保留策略。

消息请求日志清理

主要的清理机制针对 message_request 表,该表存储了系统处理的每个 API 请求的详细记录。这是数据密集程度最高的组件,需要仔细配置。

运作原理

消息请求清理使用 Bull(一个基于 Redis 的队列系统)进行可靠的任务调度和执行。当您启用自动清理并配置调度计划时,系统会创建一个以指定间隔执行的可重复任务。

清理过程遵循以下步骤:

  1. 任务调度。系统从数据库读取您的配置,并创建一个带有 cron 表达式的 Bull 任务,定义清理运行的时间。

  2. 条件构建。根据您的保留设置,系统计算一个截止日期。早于此日期的数据记录将被视为可删除。

  3. 批量删除。系统使用 PostgreSQL 的公共表表达式 (CTE) 配合 FOR UPDATE SKIP LOCKED 以可配置的批次删除记录,以避免阻塞并发操作。

  4. 进度记录。每次批量删除都会被记录,允许您监控清理进度和性能。

配置选项

通过管理仪表盘中的系统设置或通过 API 配置消息请求清理:

启用自动清理。激活或停用整个清理机制的主开关。禁用时,所有计划的清理任务都将从队列中移除。

保留天数。定义消息请求记录的保留时长。超过此天数的记录将被删除。有效范围为 1 到 365 天。默认值为 30 天。

清理计划 (Cleanup schedule)。定义清理任务执行时间的 cron 表达式。默认值为 0 2 * * *(每天凌晨 2:00)。常见的备选项包括:

计划Cron 表达式使用场景
每天凌晨 2 点0 2 * * *默认,低流量时段
每天午夜0 0 * * *替代低流量时段
每周日凌晨 3 点0 3 * * 0较小规模部署的每周清理
每 6 小时0 */6 * * *高流量系统的激进清理
每小时0 * * * *紧急清理模式

批次大小 (Batch size)。每次批量操作删除的记录数。较大的批次完成速度更快,但持有锁的时间更长。有效范围为 1,000 到 100,000。默认值为 10,000。

批量删除策略

清理服务使用先进的 PostgreSQL 特性来实现高效、非阻塞的删除:

WITH ids_to_delete AS (
  SELECT id FROM message_request
  WHERE created_at < $cutoff_date
  ORDER BY created_at ASC
  LIMIT $batch_size
  FOR UPDATE SKIP LOCKED
)
DELETE FROM message_request
WHERE id IN (SELECT id FROM ids_to_delete)

这种方法提供了几个好处:

  • 原子操作。CTE 在单个查询中选择并删除记录,避免了竞态条件。
  • 非阻塞FOR UPDATE SKIP LOCKED 允许清理操作跳过被其他事务锁定的行,防止阻塞并发插入。
  • 有序删除ORDER BY created_at ASC 首先删除最早的记录,这对于 B 树索引更有效。
  • 可配置的吞吐量。批次大小平衡了删除速度与锁定持续时间。

在批次之间,系统会暂停 100 毫秒,以减少锁竞争并给其他操作进行的机会。

端点探测日志清理

供应商端点健康检查生成的探测日志存储在 provider_endpoint_probe_logs 中。这些日志记录了针对每个配置的端点执行的定期健康检查结果。

与消息请求清理的主要区别

端点探测日志清理与消息请求清理在以下几个方面有所不同:

  • 基于环境的配置。通过环境变量而非数据库设置进行控制。
  • 分布式锁。使用基于 Redis 的领导者锁 (leader locks),以确保在多实例部署中只有一个实例运行清理任务。
  • 固定间隔。每 24 小时运行一次,而不是基于可配置的 cron 计划。

配置

在您的部署中设置以下环境变量:

# 探测日志保留天数(默认:1)
ENDPOINT_PROBE_LOG_RETENTION_DAYS=7

# 每批删除的记录数(默认:10000)
ENDPOINT_PROBE_LOG_CLEANUP_BATCH_SIZE=5000

清理任务在 CI 环境中 (CI=true) 会自动跳过,以避免干扰测试运行。

领导者锁模式 (Leader lock pattern)

在具有多个 Claude Code Hub 实例的分布式部署中,领导者锁模式确保只有一个实例执行清理:

  1. 每个实例尝试获取一个带有 5 分钟 TTL(生存时间)的 Redis 锁。
  2. 只有成功获取锁的实例才会继续执行清理。
  3. 清理完成(或失败)后,锁将被释放。
  4. 如果持锁者崩溃,TTL 确保锁最终过期,允许另一个实例接管。

这种模式防止了重复的清理工作并减轻了数据库负载。

临时文件清理

数据库备份和恢复操作会生成需要清理的临时文件。临时文件管理器提供三重保护策略:

  1. 正常清理。操作成功完成后立即删除文件。
  2. 异常清理。操作期间发生错误时删除文件。
  3. 定期清理。计划任务会移除前两种机制未清理掉的陈旧文件。

运作原理

系统维护一个内存中的 Map,跟踪所有活动的临时文件。创建文件时,会记录其创建时间戳和用途(导入或导出)。操作完成或失败时,文件将被清理并从跟踪中移除。

定期清理任务默认每小时运行一次,移除超过 6 小时的文件。这作为由于崩溃或意外错误而导致的孤立文件的安全网。

缓存清理

会话和供应商的内存缓存使用基于 TTL 的过期机制。过期条目在被访问时会自动移除,但定期清理任务可确保即使是永远不再被访问的条目也能回收内存。

缓存清理每 60 秒运行一次,扫描并移除以下各项中的过期条目:

  • 活跃会话缓存
  • 会话详细信息缓存
  • 供应商缓存

这可以防止具有高会话流动率的长运行部署中出现内存泄漏。

手动清理 API

管理员可以通过 REST API 触发手动清理,适用于需要立即删除数据或根据特定条件进行定向删除的情况。

端点

POST /api/admin/log-cleanup/manual

请求体

{
  "beforeDate": "2024-01-01T00:00:00Z",
  "afterDate": "2023-01-01T00:00:00Z",
  "userIds": [1, 2, 3],
  "providerIds": [1, 2],
  "statusCodes": [500, 502, 503],
  "statusCodeRange": { "min": 400, "max": 499 },
  "onlyBlocked": false,
  "dryRun": true
}

参数

参数类型描述
beforeDatestring (ISO 8601)删除此日期之前创建的记录
afterDatestring (ISO 8601)删除此日期之后创建的记录
userIdsnumber[]仅删除特定用户的记录
providerIdsnumber[]仅删除特定供应商的记录
statusCodesnumber[]仅删除具有特定 HTTP 状态码的记录
statusCodeRangeobject删除状态码在范围(最小值,最大值)内的记录
onlyBlockedboolean仅删除被阻止/拦截的请求
dryRunboolean预览模式:仅统计匹配的记录而不执行删除

必须指定至少一个条件。尝试在没有任何条件的情况下运行清理将返回错误,以防止意外删除所有记录。

响应

{
  "success": true,
  "totalDeleted": 15000,
  "batchCount": 2,
  "durationMs": 1250
}

授权

手动清理需要管理员权限。非管理员用户的请求将收到 401 Unauthorized 响应。

监控与可观测性

清理系统为监控和调试提供了全面的日志记录。所有清理事件都通过结构化数据记录,包括操作标识符、记录计数和耗时信息。

关键日志操作

操作描述
cleanup_queue_initialized清理队列成功初始化
auto_cleanup_scheduled根据配置调度了新的清理任务
cleanup_job_start清理任务开始执行
cleanup_job_complete清理任务成功完成
cleanup_job_failed清理任务在重试后失败
log_cleanup_batch批量删除完成
log_cleanup_dry_run预览模式完成,显示预估计数

Bull Board 监控

清理队列与 Bull Board 集成,提供了一个用于监控任务状态的 Web 界面。访问 Bull Board 端点 /admin/queues 可以:

  • 查看排队中、活动中、已完成和已失败的任务
  • 检查任务详情和错误堆栈跟踪
  • 手动触发或重试任务
  • 监控任务执行历史

需监控的指标

对于生产部署,请跟踪以下指标:

清理任务持续时间。突然增加可能表明表膨胀或锁竞争。正常的持续时间随删除的记录数而变化。

每个任务删除的记录数。跟踪数据保留模式并帮助估算存储增长。

失败任务计数。非零值表示配置问题、数据库问题或 Redis 连接问题。

临时文件清理计数。意外增加可能表明备份/恢复操作中存在文件泄露。

最佳实践

推荐的生产配置

对于大多数生产部署:

# 环境变量
ENDPOINT_PROBE_LOG_RETENTION_DAYS=7
ENDPOINT_PROBE_LOG_CLEANUP_BATCH_SIZE=5000

数据库设置(通过管理 UI):

  • 启用自动清理:true
  • 保留天数:30(根据合规要求调整)
  • 计划计划:0 2 * * *(每天凌晨 2 点)
  • 批次大小:10000(对于高流量系统可降至 5000

选择保留期

在设置保留期时平衡以下因素:

合规要求。某些法规强制要求某些类型数据的最小或最大保留期限。

调试需求。较长的保留期有助于调查不会立即显现的问题。建议为生产环境调试保留至少 30 天。

存储成本。计算每天保留的成本并相应设置期限。

查询性能。即使有适当的索引,具有数亿行的表也可能会经历较慢的查询。

处理高流量场景

对于每天处理数百万个请求的部署:

  1. 减小批次大小。较小的批次持有锁的时间更论,减少了对并发操作的影响。

  2. 在低流量时段调度。使用 cron 计划在请求量最低时运行清理。

  3. 考虑更频繁的清理。与其每天清理 30 天的数据,不如考虑每小时清理 1-2 天的数据以分散负载。

  4. 监控表膨胀。PostgreSQL 的 MVCC 可能会因大量删除而导致表膨胀。确保正确配置了自动清理 (autovacuum) 或安排定期的 VACUUM 操作。

故障排除

清理任务因超时错误失败

症状:任务因数据库超时错误失败,或完成时间越来越长。

解决方案

  • 减小 cleanupBatchSize 以缩短锁定持续时间
  • 检查表膨胀情况,必要时运行 VACUUM
  • 验证数据库连接池未耗尽
  • 检查是否存在可能与清理锁冲突的长运行查询

清理任务未运行

症状:日志或 Bull Board 中未出现清理任务。

检查项

  • 验证系统设置中的 enableAutoCleanup 是否设置为 true
  • 确认设置了 REDIS_URL 环境变量且 Redis 可访问
  • 查看日志中的 schedule_auto_cleanup_error 消息
  • 检查 /admin/queues 处的 Bull Board 以获取队列状态

清理后磁盘空间仍在增长

症状:即使清理报告成功,数据库存储使用量仍在增加。

检查项

  • 验证 PostgreSQL 的 VACUUM 是否正在运行(自动或手动)
  • 检查表膨胀情况:SELECT * FROM pg_stat_user_tables WHERE relname = 'message_request'
  • 如果膨胀严重,在维护窗口期间运行 VACUUM FULL(需要表级锁)
  • 检查其他表(如 provider_endpoint_probe_logs)是否在增长

多个实例同时运行清理

症状:日志显示清理任务在多个实例上同时运行,或出现重复的删除计数。

检查项

  • 验证所有实例都连接到同一个 Redis 服务器
  • 检查所有实例的 Redis 连接性
  • 查看日志中关于领导者锁获取失败的记录
  • 确保所有实例的 REDIS_URL 保持一致

数据库迁移问题

症状:清理任务失败,并报错缺少列或表。

解决方案

  • 运行数据库迁移以确保架构是最新的
  • 系统通过回退默认值优雅地处理某些迁移场景,但完整功能需要完整的架构

边界情况与安全特性

防止意外的全量删除

清理服务要求至少指定一个条件。如果您尝试在没有任何过滤器(无日期范围、无用户 ID、无状态码)的情况下运行清理,系统将返回错误:

Error: 未指定任何清理条件 (No cleanup conditions specified)

这可以防止意外删除所有记录。

故障不中断设计 (Fail-open design)

如果清理调度程序在应用程序启动期间初始化失败,错误会被记录,但不会阻止应用程序启动。这种“故障不中断”设计确保了清理配置错误不会导致服务中断。

但是,如果在首次访问清理队列时 Redis 不可用,则会抛出错误,因为没有 Redis 队列无法工作。

优雅降级

系统优雅地处理各种错误情况:

  • 缺少 system_settings 表。返回回退的默认设置。
  • system_settings 中缺少列。使用最小字段集并记录警告。
  • Redis 领导者锁获取失败。跳过该实例的清理。
  • 批量删除期间的清理错误。记录错误并停止当前清理任务。

软删除与硬删除

Claude Code Hub 对大多数实体(包括 message_request)实施软删除。记录具有 deleted_at 时间戳,并从查询中过滤掉。然而,清理过程执行的是硬删除,会从数据库中永久移除记录。

这种两阶段方法允许用户在 UI 中“删除”日志以立即保护隐私,同时管理员配置保留策略以进行存储管理。

总结

Claude Code Hub 中的自动清理系统提供了:

  • 多层级方法。涵盖数据库日志、探测日志、临时文件和缓存。
  • 灵活配置。主要清理采用数据库设置,探测日志采用环境变量。
  • 弹性运营。故障不中断设计、错误处理、优雅降级。
  • 分布式安全。领导者锁防止多实例部署中的冲突。
  • 性能意识。配合 SKIP LOCKED 的批量删除,可配置的批次大小。
  • 全方位可观测性。全面的日志记录和 Bull Board 集成。
  • 安全特性。预览模式、验证、防止意外删除。

配置平衡了合规要求、调试需求和存储限制的清理策略,以维持健康、高效的部署。

Previous
数据导入导出