feat(honeypot): 自动保留期清理 + 行数上限 + VACUUM 空间回收 + size 子命令
问题:honeypot_hits 是只追加审计表,写入完全由外部扫描流量驱动(不可预期、 不可节流),而原实现只在手动跑 CLI prune 时才清理,站点运行期表体积只增不减。 实测取证(本地 PostgreSQL 建同构表灌 10.5 万行真实数据): - 典型行 244 字节(含索引),10.5 万行 24 MB - 保留期清理对照(行数恒定 10 万,每轮删 25% 插 25%): 有 VACUUM 22→24MB 收敛;无 VACUUM 22→52MB 持续膨胀 - VACUUM 不缩小文件,只让空间可复用;二次实测(5 万行、连续 4 轮删插) 行数恒定 5 万、文件稳定 15MB 不再增长 改动: - 新增 HoneypotRetention 后台清理器(每小时一轮):时间闸 honeypot_retain_days + 数量闸 honeypot_max_rows,清理后调 Compact 回收空间 - db: 新增 Compact()(PG 执行 VACUUM (ANALYZE),走 GORM Exec 非事务路径)、 DeleteOldestBeyond()(跨方言通用)、ListSinceByIP()、Size() - 去掉 honeypot_hits.provider 无用索引(10 万行占 648kB,全代码库零查询使用), 并在启动时显式清理既有库上的旧索引(GORM 去 tag 不会自动删) - 修 CLI hits --ip 过滤 bug:原先取回最近 N 条再在 Go 侧筛,导致指定 IP 的 历史命中基本查不出来 → 改到 SQL 层过滤 - 新增 CLI honeypot size 子命令:报告行数、磁盘占用、时间跨度,并与两道闸对照 - 新增配置 honeypot_auto_clean / honeypot_max_rows
This commit is contained in:
@@ -104,6 +104,12 @@ func Init(typ, dsn string) (*gorm.DB, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 蜜罐表上无查询使用的索引(provider):GORM 去掉 tag 不会自动删既有索引,
|
||||
// 这里显式清理一次。失败仅告警。
|
||||
if err := dropUnusedHoneypotIndexes(db); err != nil {
|
||||
logrus.WithError(err).Warn("清理蜜罐表无用索引时异常(不影响服务启动)")
|
||||
}
|
||||
|
||||
Users = NewUsersStore(db)
|
||||
Questions = NewQuestionsStore(db)
|
||||
FollowUps = NewFollowUpsStore(db)
|
||||
@@ -215,6 +221,25 @@ func ensureFrequentlyUsedIndexes(db *gorm.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// dropUnusedHoneypotIndexes 删除蜜罐表上没有任何查询使用的索引。
|
||||
//
|
||||
// 背景:provider 字段原先带 gorm:"index",但全代码库没有一处按 provider
|
||||
// 过滤或排序(TopSources 用 max(provider) 随 group by 顺带取,不需要独立索引)。
|
||||
// 实测该索引占 10 万行约 648 kB,对一张「只增不减」的审计表是纯粹的空间浪费
|
||||
// 与写放大。去掉 GORM tag 只影响新建库,既有库上的旧索引要显式 DROP。
|
||||
//
|
||||
// 幂等:索引不存在时不报错。失败仅告警,不阻断启动。
|
||||
func dropUnusedHoneypotIndexes(db *gorm.DB) error {
|
||||
// GORM 生成的索引名规则:idx_<表名>_<列名>。
|
||||
if db.Migrator().HasIndex(&HoneypotHit{}, "idx_honeypot_hits_provider") {
|
||||
if err := db.Migrator().DropIndex(&HoneypotHit{}, "idx_honeypot_hits_provider"); err != nil {
|
||||
return errors.Wrap(err, "drop unused honeypot index")
|
||||
}
|
||||
logrus.Info("已删除蜜罐表上无查询使用的 provider 索引")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fixPostgresSequences(db *gorm.DB) error {
|
||||
// 使用配置的 schema(未配置时回退 public),避免硬编码 nekobox。
|
||||
schema := conf.Database.Schema
|
||||
|
||||
Reference in New Issue
Block a user