Skip to content

fix(info): 删除硬编码假数据并接入真实 runtime、storage 与 Raft 状态 #410

Description

@AlexStocks

Bug 描述

INFO 当前返回大量硬编码值,与真实进程、配置、运行平台、Redis 8.8.1 兼容基线和 Raft 状态无关。监控系统、客户端和运维人员会把这些值当作服务事实,当前输出会提供错误的版本、OS、端口、PID、uptime 和 cluster 状态。

对比基线:

  • Rust Kiwi:main@3164d4a0fead580ac6701fb0595e50193c4edff9(2026-07-31)
  • kiwi-cpp:unstable@0fa4f1b95ff2f89873d06eb86de40532dd91d146;其 #176 也要求让 INFO 输出与 Redis 对齐

当前源码证据

InfoCmd::do_cmd() 不读取传入的 Storage,也没有 server/runtime/Raft 状态 provider,而是直接拼接常量:

  • redis_version:7.0.0,与项目固定的 Redis 8.8.1 兼容基线不一致;
  • os:Windows、multiplexing_api:select、gcc_version:0.0.0,在 Linux/macOS 和当前 Tokio 架构下均不代表真实运行时;
  • process_id:1、tcp_port:7379、uptime_in_seconds:1、executable:/path/to/kiwi-server,不读取实际进程和配置;
  • redis_mode:standalone、cluster_enabled:0、cluster_state:disabled,即使启用 OpenRaft 仍报告 standalone/disabled;
  • 未知 section 被静默降级为一小段 Server 信息,且 default 只返回 Server/Cluster 两节,没有建立 Redis 8.8.1 的 section 选择合同。

项目自己的兼容要求已经把 INFO 列为必须验证的发现接口,系统稳定门禁也要求持续记录 请求延迟、吞吐、资源、compaction stall 和 Raft commit/apply latency。当前 INFO 既不满足兼容发现,也不能作为运维观测入口。

与现有 Issue 的关系

当前没有开放 Issue 对 INFO 的硬编码错误和 Redis 8.8.1 section 合同负责。

建议设计

1. 注入只读状态 Provider

不要在 cmd crate 引入无边界全局变量。为 InfoCmd 注入只读、可测试的 ServerInfoProvider/等价接口,由 server startup 组合真实来源:

  • build identity:Kiwi 版本、Git SHA/build id、目标架构;
  • process identity:OS、PID、可执行文件、启动时间、实际监听端口、配置文件身份;
  • network/client:当前连接数、累计连接、拒绝/超时/协议错误;
  • storage/RocksDB:实例数、路径身份、内存/缓存、WAL、compaction、读写错误与 keyspace;
  • runtime/executor:queue、running worker、completed/failed/timed-out、queue wait/execution time;
  • Raft:是否启用、node id、role/leader、term、membership、last log/applied/snapshot、commit/apply latency 和 unhealthy 状态。

Provider 返回一次有边界的 snapshot;组装 INFO 时不得在每个字段重复获取锁、执行无界 RocksDB 扫描或发起网络 RPC。

2. 固定 Redis 8.8.1 section 合同

先用仓库规定的 exact Redis 8.8.1 Oracle 获取 INFO 的参数、section、默认集合、未知 section、字段格式和 RESP2/RESP3 返回类型证据,再实现 Kiwi 支持的 section。

至少分阶段覆盖:

  1. server、clients、stats、persistence、replication/cluster、keyspace;
  2. memory、cpu、commandstats、latencystats、errorstats;
  3. default、all、everything 和多 section 组合。

对 Redis 有字段但 Kiwi 暂无等价来源的情况,应根据兼容证据决定“真实的零/状态值”或“暂不输出”,不得继续填入看似真实的常量。Kiwi 扩展字段使用稳定的 kiwi_* 命名并写入文档。

3. 安全和性能边界

  • 不输出 requirepass、完整命令参数、用户 key、凭据或未脱敏内部地址;
  • command/错误指标使用固定命令表和有界 label,不允许攻击者输入制造无界基数;
  • RocksDB property 获取必须有 timeout/缓存策略,单次 INFO 不得阻塞 storage runtime 或触发全库遍历;
  • 指标读取失败应在对应 section 显示可诊断状态或省略字段,不能退回硬编码假数据;
  • INFO 自身应继续是只读命令,不改变 Raft/storage 状态。

验证范围

命令级兼容测试

  • 用 exact Redis 8.8.1 对照无参数、单 section、多 section、default、all、everything、未知 section 的 raw RESP;
  • RESP2/RESP3 返回均为正确的 bulk payload,CRLF、section header、字段分隔和顺序合同有测试;
  • INFO server 不再出现固定 7.0.0、Windows、PID 1、端口 7379、uptime 1 或占位 executable。

真实进程测试

  • 在 Linux 随机端口启动 standalone,校验 PID、port、OS/arch、uptime 单调增长、配置身份和实际模式;
  • 建立/关闭客户端连接,验证 clients/stats 的真实变化;
  • 执行读写、错误、timeout 和 compaction/RocksDB 活动,验证相关 counter/latency 来自真实调用点;
  • 启动三节点 OpenRaft,验证 leader/follower、node id、term、membership、applied/snapshot 等字段与 Raft metrics 一致;
  • 重启后 PID/uptime 更新,持久化/复制状态仍与实际数据一致;
  • 未启用 Raft 时不得伪装 leader/cluster healthy;启用 Raft 时不得报告 standalone/disabled。

非目标

验收标准

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions