Nexus 3 npm 仓库迁移踩坑手册 📅 2026/7/7 7:21:12 根因分析npm-group [npm-proxy, npm-hosted]npm-proxy远程代理仓库缓存 npmjs 公共包包版本齐全npm-hosted本地托管仓库所有私有发包上传于此两仓库存在重叠包同名group 合并元数据时冲突Nexus 3 内部解析重叠包的dist-tags/versions产生异常抛 5001.3 仓库架构用户请求 → npm-group统一入口 ├─ npm-proxy远程缓存~X万包 └─ npm-hosted本地存储~Y万包2. 修复方案四阶段迁移阶段操作并发说明1全量检查重叠包12 线程对 proxy/hosted 共有包逐包请求 group标记 500 失败2计算缺失版本串行获取 proxy 全量版本与 hosted 差集得出需补清单3多线程下载→上传4-20 线程从远程源下载 tarball上传到 hosted4验证 重建12 线程逐一复查失败包确认 group 恢复正常最终放弃割接方案改为修改 Nexus 源码新增hostedFirst版本级合并策略。3. 断点续传机制# 核心基于结果文件的 Set 去重 processed set() if os.path.exists(RESULT_FILE): for line in open(RESULT_FILE): r json.loads(line) processed.add((r[name], r[version])) pending [e for e in all_entries if (e[name], e[version]) not in processed]结果文件fix500_result.jsonl逐行追加每行包含{name, version, action, source, size}重启时加载全部已处理 key → Set 去重 → 筛选待处理支持任意次数中断重启进度不丢每个 worker 完成立即flush写入单条不丢失4. 性能踩坑实录4.1 坑一下载源优先级现象早期下载源配置npmmirror → npmjs → proxy单包耗时 3 分钟速率 ~0.5/min根因npmmirror 为国内镜像 CDN但走公司代理后限速至300 KB/s而内部 Nexus proxy 仓库直连可达6.5 MB/s22 倍差距npmmirror走代理: 300 KB/s → 55MiB/186s proxy内部直连: 6.5 MB/s → 55MiB/8.6s解决源优先级改为proxy → npmmirror → npmjs4.2 坑二代理绕过现象试图让 npmmirror 不走代理直连结果彻底超时根因公司网络所有出站流量必须走指定代理直连 npmmirror CDN 的 TCP SYN 被直接丢弃解决回退成所有请求统一走代理利用内部 Nexus proxy 仓库作为首选源4.3 坑三并发悖论现象20 线程反而比 4 线程慢根因代理出口带宽固定~3 MB/s每个线程分到的带宽 总带宽 / 线程数线程数单线程带宽55MiB 文件耗时完成间隔2~1.5 MB/s~35s~18s8~375 KB/s~150s~19s20~150 KB/s~370s~18s结论单文件完成时间与线程数成反比但完成间隔吞吐量恒定由总带宽÷文件大小决定实践策略大文件段10MB2-4 线程减少连接开销和内存小文件段1MB8-20 线程充分利用 HTTP 并发4.4 坑四大包家族迁移过程中发现两类巨型 npm 包严重拖慢进度包家族版本数总大小最大单包特点iconify/json1,491~57 GB84 MiB全图标库 JSON每个版本独立打包全部图标swc/core-*8,580~20 GB49 MiBRust 编译的 JS 工具链每个平台/架构各一个包影响这两族包仅占总数的 3%却消耗了80% 的迁移时间iconify 约 8 小时swc 约 3 小时应对大包段降低并发避免互抢确保优先用内部 proxy 源下载4.5 性能演进总览阶段配置速率瓶颈初始15 线程npmjs 优先~2/snpmjs 国际线路限速优化120 线程npmmirror 优先~7/s → 2/s大包出现后回归回退20 线程npmmirror 直连~0.5/min直连超时 全回退修正8 线程走代理~1/minproxy 慢 大包翻盘2-8 线程proxy 优先~20/s小包段起飞5. 磁盘空间优化迁移完成后npm-proxy与npm-hosted存在大量重叠冗余包。清理逻辑遍历 proxy 中所有包在 hosted 中找到同名包则删除 hosted 元数据。Nexus 内部 blob store 通过 Compact blob store 定时任务回收释放空间。实际回收数百 GB6. 操作手册6.1 环境变量export NEXUS_URLhttp://NEXUS_HOST:8081/nexus/content export NEXUS_USERUSER export NEXUS_PASSPASS6.2 脚本参数python3 nexus-fix-500.py --phase 3 --workers 8参数默认说明--phase 1阶段1检查 group 500 包--phase 2阶段2计算缺失版本--phase 3阶段3多线程迁移主力--phase 4阶段4验证修复--phase 5阶段5更新 group 配置--workers N15迁移并发数--skip-phase1-跳过阶段1用已有清单--skip-phase2-跳过阶段2用已有清单6.3 典型用法# 首次完整执行 python3 nexus-fix-500.py # 断点续传只跑迁移阶段 python3 nexus-fix-500.py --phase 3 --workers 8 # 换机器续传拷贝 migration_data/ 目录即可 scp -r migration_data/ new-host:/path/to/ python3 nexus-fix-500.py --phase 3 --workers 86.4 前置依赖Python 3.6requests,urllib3Nexus REST API 可用网络可达NEXUS_HOST:80816.5 断点续传文件清单文件用途大小参考fix500_result.jsonl已处理记录核心~7 MiBfix500_versions.jsonl待处理版本清单~38 MiBfix500_list.jsonl失败包清单~300 KiBmigration_data/所有数据目录~46 MiB