背景
最近公司内部的 Nexus 私服(版本 3.22.0)突然出现异常,开发同学反馈打包时拉取 jar 包报错 401 Unauthorized。
经过初步排查,发现了一个非常奇怪的现象:
- 重启大法:重启 Nexus 服务后,服务可以正常使用,构建也正常。
- 5分钟魔咒:大约运行 5-10 分钟后,故障复现。
- 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.jar对security和config库执行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)。
-
创建 Blob Store:
进入设置 ->Blob Stores,确保默认的defaultBlob Store 的Path指向了旧数据所在的目录(例如/nexus-data/blobs/default)。这一步至关重要,只要路径对,数据就在。 -
重建仓库:
凭记忆或文档,手动创建之前的仓库(如maven-releases,maven-snapshots等)。- 关键点:创建仓库时,
Blob store选项一定要选择上面那个包含旧数据的default。
- 关键点:创建仓库时,
步骤四:灾难恢复(Reconcile)
此时仓库建立好了,但浏览仓库里面是空的,因为新的数据库里没有索引。我们需要运行修复任务来“认领”这些文件。
- 进入 System -> Tasks。
- 点击 Create task。
- 选择类型:Admin – Repair – Reconcile component database from blob store。
- 配置任务:
- Blob store: 选择存放旧数据的
default。
- Blob store: 选择存放旧数据的
- 保存并点击 Run。
结果
任务运行了几分钟后(取决于数据量),日志显示扫描了磁盘上的 jar 包并重建了数据库记录。
刷新 Browse 页面,原本消失的 jar 包全部恢复!所有的 401 报错彻底消失,服务恢复稳定。
总结与教训
- Nexus 的存储机制:Nexus 的数据分为两部分:
Blob Store(物理文件) 和OrientDB(元数据索引)。只要Blob Store还在,数据库坏了是可以救回来的。 - 备份的重要性:这次是因为没有有效的
.bak自动备份文件,才被迫使用了重置数据库的方案。建议检查 Nexus 的Admin - Export databases for backup任务是否正常开启。 - OrientDB 的脆弱性:Nexus 3.x 早期版本依赖的 OrientDB 在异常断电或磁盘压力大时容易损坏,遇到无法解释的权限问题,多半是
security库坏了。