Press "Enter" to skip to content

[实战] 记一次 Nexus 私服频繁 401 及菜单消失的故障排查与数据恢复

背景

最近公司内部的 Nexus 私服(版本 3.22.0)突然出现异常,开发同学反馈打包时拉取 jar 包报错 401 Unauthorized

经过初步排查,发现了一个非常奇怪的现象:

  1. 重启大法:重启 Nexus 服务后,服务可以正常使用,构建也正常。
  2. 5分钟魔咒:大约运行 5-10 分钟后,故障复现。
  3. UI 异常:刚启动时左侧菜单栏能看到 Browse 选项,故障发生时,刷新页面 Browse 菜单直接消失,且此时构建请求全部报 401。

排查过程

1. 日志与磁盘检查

首先检查了 /nexus-data 目录所在的磁盘空间,使用 df -h 查看,磁盘空间充足(剩余 400G+),排除了磁盘满导致的数据库锁定。

查看 nexus.log,启动日志一切正常,直到故障发生时,并未出现明显的 Exception 堆栈,这让排查陷入僵局。

2. 故障分析

结合“重启能用一会”和“菜单消失”的现象,推测问题出在 Nexus 的权限认证缓存(Cache)与底层数据库(OrientDB)的数据交互上

  • 启动初期:Nexus 使用内存中的缓存数据进行权限校验,一切正常。
  • 缓存过期后:Nexus 尝试回源读取底层 security 数据库进行鉴权。此时若读取失败(数据库逻辑损坏或死锁),系统判定当前用户无权限,导致菜单消失和 401。

3. 尝试修复(踩坑记录)

为了解决问题,我们尝试了以下几种方案,但均未彻底解决:

  • 方案 A:数据库自带修复工具
    使用 Nexus 自带的 nexus-orient-console.jarsecurityconfig 库执行 repair database
    结果:控制台显示 0 errors,修复后重启,问题依旧。这说明数据库文件结构没坏,但内部逻辑可能已经错乱。

  • 方案 B:清理 WAL 日志
    尝试移除了数据库目录下的 .wal (Write Ahead Log) 文件,试图强制数据库忽略未完成的事务。
    结果:重启后 WAL 文件重新生成,问题依旧。

  • 方案 C:调整 Ehcache 策略
    尝试修改 ehcache.xml 延长缓存时间。
    结果:由于容器环境限制及配置挂载困难,且治标不治本,放弃此方案。

由于没有近期的有效备份文件(.bak),无法使用标准的 Restore 功能回滚,情况一度非常危急。

终极解决方案:重置数据库 + 重建索引

在确认 Blob Store(物理文件存储) 完好无损的情况下,我们决定采取“置之死地而后生”的方案:重置损坏的数据库,保留物理文件,通过扫描文件重建索引。

⚠️ 警告:此操作会导致所有用户账号、角色、仓库配置丢失,需要重新手动配置,但能保住所有 jar 包数据。

步骤一:重置数据库

进入容器内部,找到数据存储目录,将损坏的数据库文件夹重命名(相当于删除,让 Nexus 重新生成全新的库)。

# 进入数据库目录
cd /nexus-data/db

# 重命名 security 库(解决 401 问题)
mv security security_broken_backup

# 重命名 config 和 component 库(解决仓库元数据错乱问题)
mv config config_broken_backup
mv component component_broken_backup

步骤二:重启并获取初始密码

杀掉 Nexus 进程触发重启:

kill -9 <JAVA_PID>

重启后,Nexus 会发现数据库不存在,自动初始化全新的数据库。我们需要获取新的管理员密码:

cat /nexus-data/admin.password

步骤三:重建仓库配置

使用新密码登录 Nexus 界面(此时是一个全新的空白 Nexus)。

  1. 创建 Blob Store
    进入设置 -> Blob Stores,确保默认的 default Blob Store 的 Path 指向了旧数据所在的目录(例如 /nexus-data/blobs/default)。这一步至关重要,只要路径对,数据就在。

  2. 重建仓库
    凭记忆或文档,手动创建之前的仓库(如 maven-releases, maven-snapshots 等)。

    • 关键点:创建仓库时,Blob store 选项一定要选择上面那个包含旧数据的 default

步骤四:灾难恢复(Reconcile)

此时仓库建立好了,但浏览仓库里面是空的,因为新的数据库里没有索引。我们需要运行修复任务来“认领”这些文件。

  1. 进入 System -> Tasks
  2. 点击 Create task
  3. 选择类型:Admin – Repair – Reconcile component database from blob store
  4. 配置任务:
    • Blob store: 选择存放旧数据的 default
  5. 保存并点击 Run

结果

任务运行了几分钟后(取决于数据量),日志显示扫描了磁盘上的 jar 包并重建了数据库记录。

刷新 Browse 页面,原本消失的 jar 包全部恢复!所有的 401 报错彻底消失,服务恢复稳定。

总结与教训

  1. Nexus 的存储机制:Nexus 的数据分为两部分:Blob Store (物理文件) 和 OrientDB (元数据索引)。只要 Blob Store 还在,数据库坏了是可以救回来的。
  2. 备份的重要性:这次是因为没有有效的 .bak 自动备份文件,才被迫使用了重置数据库的方案。建议检查 Nexus 的 Admin - Export databases for backup 任务是否正常开启。
  3. OrientDB 的脆弱性:Nexus 3.x 早期版本依赖的 OrientDB 在异常断电或磁盘压力大时容易损坏,遇到无法解释的权限问题,多半是 security 库坏了。
发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注