一、系统要求

1.1、专用操作系统用户

为了满足安全的需求,建议采用低权限用户运行nexus

  1. [root@nexus ~]# useradd nexus

1.2、系统参数调优

nexus 需求linux句柄数为65535 或更高,以避免数据丢失

[root@nexus ~]# echo "nexus soft nofile 204800"  >> /etc/security/limits.conf
[root@nexus ~]# echo "nexus hard nofile 204800"  >> /etc/security/limits.conf
[root@nexus ~]# echo "nexus soft nproc 204800"  >> /etc/security/limits.conf
[root@nexus ~]# echo "nexus hard nproc 204800 "  >> /etc/security/limits.conf

nexus内置Elasticsearch,需要设置vm.max_map_count=262144

[root@nexus ~]# echo "vm.max_map_count=262144" >> /etc/sysctl.conf
[root@nexus ~]# sysctl -p

1.3、JAVA

nexus 需要 Java 8 Runtime Environment(JRE),这里采用openjdk,如果使用Oracle JDK,建议采用JDK8u221之前版本,避免Oracle 律师函警告

[root@nexus ~]# yum install java-1.8.0-openjdk  java-1.8.0-openjdk-devel
[root@nexus ~]# java -version
openjdk version "1.8.0_322"
OpenJDK Runtime Environment (build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM (build 25.322-b06, mixed mode)

特别注意的是,如果服务器上有多个JDK或JRE时时,需要修改/bin/nexusINSTALL4J_JAVA_HOME_OVERRIDE= 来指定,避免启动时出现异常

1.4、资源需求

nexus主要的性能瓶颈为IO和网络,建议优先考虑IO和网络。针对CPU和内存,可以参考下表

内存 JVM优化参数
8GB -Xms2703M -Xmx2703M -XX:MaxDirectMemorySize=2703M
12GB -Xms4G -Xmx4G -XX:MaxDirectMemorySize=4014M
16GB -Xms4G -Xmx4G -XX:MaxDirectMemorySize=6717M
32GB -Xms6G -Xmx6G -XX:MaxDirectMemorySize=15530M
64GB -Xms8G -Xmx8G-XX:+UseG1GC-XX:MaxDirectMemorySize=35158M
关于nexus内存配置的规范:
  • 服务器最小内存为8G
  • -Xmx 和 -Xms 必须相等
  • -Xms 最小为 2703MB
  • -XX:MaxDirectMemorySize 最小为 2703MB (为OrientDB配置,若使用OrientDB,必须配置此项)
  • 最小未分配内存必须大于服务器总内存1/3
  • -Xmx 和 -XX:MaxDirectMemorySize 之和必须小于服务器总内存 2/3

二、nexus部署

2.1、nexus 目录结构

nexus安装包解压后主要包括如下两个目录,其中nexus-3.37.3-02 为运行目录,sonatype-work为数据目录。

Nexus Repository Manager 3 学习文档 - 图1

运行目录结构如下图所示

Nexus Repository Manager 3 学习文档 - 图2

  • bin/ 目录下为服务启动脚本及相关配置
  • etc/ 目录下为配置文件
  • lib/ 目录下为Apache Karaf的二进制库
  • public/ 目录下为nexus前端静态文件
  • system/ 目录下为程序组件和插件
    数据目录结构如下图
  • blobs/ blobs存储父目录
  • cache/ Karaf 缓存
  • db/ OrientDB 数据库
  • elasticsearch/ elasticsearch数据
  • etc/ nexus配置
  • health-check/ 运行状况缓存报告
  • keystores/ 密钥
  • log/ 日志包括nexus程序日志,HTTP请求日志,JVM日志,Karaf 日志审计日志,定时任务日志
  • tmp/ 临时存储

2.2、部署nexus

2.2.1、下载nexus

nexus可以从官网下载,下载地址为 Download Archives - Repository Manager 3 (sonatype.com)

[root@nexus ~]# mkdir /opt/nexusHome/
[root@nexus ~]# chown -R nexus.nexus /opt/nexusHome/
[root@nexus ~]# su - nexus
[nexus@nexus ~]$ wget -c https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/3/nexus-3.37.3-02-unix.tar.gz
[nexus@nexus ~]$ tar zvxf nexus-3.37.3-02-unix.tar.gz -C /opt/nexusHome/

2.2.2、修改nexus配置

# 修改nexus启动配置
[nexus@nexus ~]$ cd /opt/nexusHome/nexus-3.37.3-02/bin/
# 修改JVM参数
# 服务器为4C16G,所以需要修改JVM参数
# 默认JVM 为 -Xms2703m -Xmx2703m -XX:MaxDirectMemorySize=2703m
# 修改为 -Xms4G -Xmx4G -XX:MaxDirectMemorySize=6717m
[nexus@nexus bin]$ sed -i 's/-Xms2703m/-Xms4G/g' nexus.vmoptions
[nexus@nexus bin]$ sed -i 's/-Xmx2703m/-Xmx4G/g' nexus.vmoptions
[nexus@nexus bin]$ sed -i 's/2703/6717/g' nexus.vmoptions
[nexus@nexus bin]$ cat nexus.vmoptions 
-Xms4G
-Xmx4G
-XX:MaxDirectMemorySize=6717m
-XX:+UnlockDiagnosticVMOptions
-XX:+LogVMOutput
-XX:LogFile=../sonatype-work/nexus3/log/jvm.log
-XX:-OmitStackTraceInFastThrow
-Djava.net.preferIPv4Stack=true
-Dkaraf.home=.
-Dkaraf.base=.
-Dkaraf.etc=etc/karaf
-Djava.util.logging.config.file=etc/karaf/java.util.logging.properties
-Dkaraf.data=../sonatype-work/nexus3
-Dkaraf.log=../sonatype-work/nexus3/log
-Djava.io.tmpdir=../sonatype-work/nexus3/tmp
-Dkaraf.startLocalConsole=false
-Djdk.tls.ephemeralDHKeySize=2048
-Djava.endorsed.dirs=lib/endorsed
# 修改启动用户为nexus
[nexus@nexus bin]$ sed -i 's/#run_as_user=""/run_as_user="nexus"/g' nexus.rc 
[nexus@nexus bin]$ cat nexus.rc 
run_as_user="nexus"
# 修改启动命令中的JAVA_HOME
[nexus@nexus bin]$ sed -i 's/# INSTALL4J_JAVA_HOME_OVERRIDE=/INSTALL4J_JAVA_HOME_OVERRIDE=\/usr\/lib\/jvm\/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/g' nexus
[nexus@nexus bin]$ head -20 nexus
#!/bin/sh
# chkconfig:         2345 75 15
# description:       nexus
### BEGIN INIT INFO
# Provides:          nexus
# Required-Start:    $local_fs $network $remote_fs $syslog $time
# Required-Stop:     $local_fs $network $remote_fs $syslog $time
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: nexus
### END INIT INFO
# Uncomment the following line to override the JVM search sequence
INSTALL4J_JAVA_HOME_OVERRIDE=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64
# Uncomment the following line to add additional VM parameters
# INSTALL4J_ADD_VM_PARAMS=
INSTALL4J_JAVA_PREFIX=""
GREP_OPTIONS=""

2.2.3、启动nexus

[nexus@nexus bin]$ ./nexus start
Starting nexus
# 这里比较慢,需要等待,主语观察nexus进程是否存在,同时关注一下log是否有异常

当log出现如下内容后,服务启动成功

Nexus Repository Manager 3 学习文档 - 图3

2.2.4、访问nexus并修改admin账号

可通过浏览器访问nexus,如下图

Nexus Repository Manager 3 学习文档 - 图4

nexus3为了安全,将密码存放在$NEXUS_HOME/sonatype-work/nexus3/admin.password文件内

Nexus Repository Manager 3 学习文档 - 图5

[nexus@nexus nexus3]$ cat /opt/nexusHome/sonatype-work/nexus3/admin.password 
4216a668-bf62-40b3-bd65-0b31446c05db

登陆后修改nexus admin密码,至此,nexus部署完成

三、nexus配置仓库

3.1、nexus配置maven仓库

3.1.1、nexus配置本地SNAPSHOTS仓库

  1. 创建SNAPSHOT仓库

Nexus Repository Manager 3 学习文档 - 图6


  1. 版本规则选择Snapshot、Strict,Blod 如果为生产,建议优先创建blob,这里采用default

Nexus Repository Manager 3 学习文档 - 图7

  1. 创建Snapshot仓库权限规则,赋予Snapshot仓库的全部权限(admin)

Nexus Repository Manager 3 学习文档 - 图8

  1. 创建SnapShot仓库管理员账号,并赋予刚配置好的权限规则

Nexus Repository Manager 3 学习文档 - 图9


  1. 至此Snapshot仓库配置完毕

3.1.2、nexus配置本地Release仓库

Release仓库配置方法和Snapshot相同,如下图
  1. 创建maven Release仓库

Nexus Repository Manager 3 学习文档 - 图10

  1. 创建 Release仓库权限规则

Nexus Repository Manager 3 学习文档 - 图11

  1. 创建Release仓库管理员账号

Nexus Repository Manager 3 学习文档 - 图12

3.1.3、nexus配置代理仓库

针对纯内网用户,通常选择一台可访问公网服务器来部署nexus,同时代理公网三方仓库以便于开发同学使用,配置方法如下图

Nexus Repository Manager 3 学习文档 - 图13

可根据此方法创建如下常用仓库:

3.1.4、nexus配置public group

为了简化开发同学配置maven,通常会配置一个maven group以便于使用,此group会包含所有的maven本地仓库及三方仓库,配置方法如下图

Nexus Repository Manager 3 学习文档 - 图14

当用户使用时,可以在settings.xml中添加如下代码即可

<mirror>
    <id>localPublic</id>
    <mirrorOf>*</mirrorOf>
    <name>本地仓库</name>
    <url>http://172.168.1.55:8081/repository/mavenPublic/</url>
</mirror>

3.2、nexus配置其他资源仓库

nexus配置node、golang、python、docker等仓库的方式同node基本相同,需要注意的是,配置本地仓库需要单独添加realms,如下图

Nexus Repository Manager 3 学习文档 - 图15

四、nexus高可用

4.1、nexus proxy实现高可用

此方案为官方提供的高可用方案,可实现读写分离及nexusHA集群,并且具有横向扩展能力,适用于所有nexus可管理的资源,劣势在于proxy节点需要缓存一份依赖,在第一次构建时会降低打包速度,同时随着proxy节点的增加,资源使用量较大。

现通过maven 仓库举例说明。

4.1、根据以上内容,在master节点的nexus仓库创建maven仓库,包括Release、SNAPSHOT及三方仓库代理

Nexus Repository Manager 3 学习文档 - 图16

4.2、根据以上内容,在master节点的nexus仓库创建maven group 作为public 仓库

Nexus Repository Manager 3 学习文档 - 图17

4.3、在nexus slave 也就是 nexus proxy节点创建maven proxy仓库,并将远端仓库配置为nexus master的public仓库

Nexus Repository Manager 3 学习文档 - 图18

Nexus Repository Manager 3 学习文档 - 图19

4.4、修改maven的settings.xml 实现读写分离

Nexus Repository Manager 3 学习文档 - 图20

Nexus Repository Manager 3 学习文档 - 图21

Nexus Repository Manager 3 学习文档 - 图22

4.5、测试打包及上传

测试demo项目打包结果

Nexus Repository Manager 3 学习文档 - 图23

测试demo项目向远端仓库deploy制品

Nexus Repository Manager 3 学习文档 - 图24

Nexus Repository Manager 3 学习文档 - 图25

至此,以proxy 的方式实现了nexus的HA集群,并且实现了读写分离,为了提高吞吐,可增加proxy节点的数量,通过nginx实现负载均衡。

五、备份、备份恢复、存储空间释放

5.1、orientdb备份

配置备份任务

Nexus Repository Manager 3 学习文档 - 图26

任务运行结果

Nexus Repository Manager 3 学习文档 - 图27

5.2、blob备份

备份 ${NexusHome}/${dataDir}/blobs 目录即可

5.3、恢复orientdb数据

5.3.1、停止nexus服务
5.3.2、移除Nexus Repository Manager 3 学习文档 - 图28{dataDir}/db目录下的 componentconfigsecurity
5.3.3、将备份的数据文件复制到${NexusHome}/${dataDir}/restore-from-backup 目录下
5.3.5、还原和数据库版本对应的blob备份
5.3.6、启动nexus并验证服务
5.3.7、验证无误后清理${NexusHome}/${dataDir}/restore-from-backup目录下备份文件

5.4、存储空间释放

5.4.1、配置blobs回收任务

Nexus Repository Manager 3 学习文档 - 图29

5.4.2、统计当前数据目录使用情况

Nexus Repository Manager 3 学习文档 - 图30

5.4.3、删除nexus中缓存的依赖

Nexus Repository Manager 3 学习文档 - 图31

5.4.4、查看当前nexus 数据目录磁盘使用率

Nexus Repository Manager 3 学习文档 - 图32

5.4.5、执行blobs空间回收任务后再次查看nexus空间使用率

Nexus Repository Manager 3 学习文档 - 图33

Nexus Repository Manager 3 学习文档 - 图34

至此完成空间回收

六、nexus 常见故障修复

6.1、orientdb异常修复

现象:nexus因 OOM 服务异常中断,重启服务后访问页面异常,日志如下

2020-09-29 13:16:37,261+0800 ERROR [ForkJoinPool.commonPool-worker-1]  *SYSTEM org.sonatype.nexus.orient.DatabaseInstanceImpl - Lifecycle operation start failed
com.orientechnologies.orient.core.exception.OStorageException: Cannot open local storage '/opt/nexusHome/sonatype-work/nexus3/db/component' with mode=rw
        DB name="component"
        at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:323)
        at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.open(ODatabaseDocumentTx.java:259)
        at org.sonatype.nexus.orient.DatabaseManagerSupport.connect(DatabaseManagerSupport.java:143)
        at org.sonatype.nexus.orient.DatabaseInstanceImpl.doStart(DatabaseInstanceImpl.java:56)
        at org.sonatype.goodies.lifecycle.LifecycleSupport.start(LifecycleSupport.java:104)
        at org.sonatype.goodies.lifecycle.Lifecycles.start(Lifecycles.java:44)
        at org.sonatype.nexus.orient.DatabaseManagerSupport.createInstance(DatabaseManagerSupport.java:252)
        at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1688)
        at org.sonatype.nexus.orient.DatabaseManagerSupport.instance(DatabaseManagerSupport.java:231)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
        at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.NullPointerException: null
        at com.orientechnologies.orient.core.storage.impl.local.paginated.wal.ODiskWriteAheadLog.cutTill(ODiskWriteAheadLog.java:919)
        at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.makeFullCheckpoint(OAbstractPaginatedStorage.java:3705)
        at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.recoverIfNeeded(OAbstractPaginatedStorage.java:3936)
        at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:288)
        ... 17 common frames omitted

解决方案:此问题可通过nexus自带的orientdb console工具修复

# 虽然服务运行中也可以修复,但是为了避免用户添堵,还是先停了服务吧
# 一定不要使用root用户修复,root权限下执行命令修复
# 会修改 ${NexusHome}/sonatype-work/nexus3/db/ 目录下文件权限,导致服务异常
[root@nexus bin] # su - nexus 
# 进入orientdb的console
[nexus@nexus bin]$ java -jar ${NexusHome}/lib/support/nexus-orient-console.jar
# 连接数据库,可通过此语句链接 accesslog、analytics、audit、componet、config、security 库
# 默认账密为 admin:admin
orientdb> CONNECT PLOCAL:/data/sonatype-work/nexus3/db/component admin admin
# 依次执行如下语句修复
# 重建索引
orientdb> REBUILD INDEX *
# 修复图形
orientdb> REPAIR DATABASE --fix-graph
# 修复链接
orientdb> REPAIR DATABASE --fix-links
# 修复异常的ridbag数据结构
orientdb> REPAIR DATABASE --fix-ridbags
# 修复异常的bonsai
orientdb> REPAIR DATABASE --fix-bonsai
# 断开连接
orientdb> DISCONNECT

针对此问题作出的预案

  • 配置task任务,备份orientdb
  • 扩容服务器内存,并修改jvm优化参数

6.2、JVM导致服务异常

此问题来自于官方博客
现象:服务访问异常,日志内容如下

2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - Database 'analytics' uses 1,726MB/2,048MB of DISKCACHE memory, while Heap is not completely used (usedHeap=2210MB maxHeap=3641MB). To improve performance set maxHeap to 2652MB and DISKCACHE to 3036MB
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - -> Open server.sh (or server.bat on Windows) and change the following variables: 1) MAXHEAP=-Xmx2652M 2) MAXDISKCACHE=3036
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - Database 'security' uses 1,726MB/2,048MB of DISKCACHE memory, while Heap is not completely used (usedHeap=2210MB maxHeap=3641MB). To improve performance set maxHeap to 2652MB and DISKCACHE to 3036MB
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - -> Open server.sh (or server.bat on Windows) and change the following variables: 1) MAXHEAP=-Xmx2652M 2) MAXDISKCACHE=3036
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - Database 'component' uses 1,726MB/2,048MB of DISKCACHE memory, while Heap is not completely used (usedHeap=2210MB maxHeap=3641MB). To improve performance set maxHeap to 2652MB and DISKCACHE to 3036MB
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - -> Open server.sh (or server.bat on Windows) and change the following variables: 1) MAXHEAP=-Xmx2652M 2) MAXDISKCACHE=3036
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - Database 'audit' uses 1,726MB/2,048MB of DISKCACHE memory, while Heap is not completely used (usedHeap=2210MB maxHeap=3641MB). To improve performance set maxHeap to 2652MB and DISKCACHE to 3036MB
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - -> Open server.sh (or server.bat on Windows) and change the following variables: 1) MAXHEAP=-Xmx2652M 2) MAXDISKCACHE=3036
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - Database 'config' uses 1,726MB/2,048MB of DISKCACHE memory, while Heap is not completely used (usedHeap=2210MB maxHeap=3641MB). To improve performance set maxHeap to 2652MB and DISKCACHE to 3036MB
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - -> Open server.sh (or server.bat on Windows) and change the following variables: 1) MAXHEAP=-Xmx2652M 2) MAXDISKCACHE=3036
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - Database 'accesslog' uses 1,726MB/2,048MB of DISKCACHE memory, while Heap is not completely used (usedHeap=2210MB maxHeap=3641MB). To improve performance set maxHeap to 2652MB and DISKCACHE to 3036MB
2017-05-05 22:57:18,268-0400 INFO  [Timer-1] *SYSTEM com.orientechnologies.common.profiler.OAbstractProfiler$MemoryChecker - -> Open server.sh (or server.bat on Windows) and change the following variables: 1) MAXHEAP=-Xmx2652M 2) MAXDISKCACHE=3036

解决方案:
根据日志中的信息调整JVM参数,然后重启服务,如果还出现此日志,则重复调整

# 在 ${NexusHome}/${AppDir}/bin/nexus.vmoptions 中修改
-Xms2652M -Xmx2652M -XX:MaxDirectMemorySize=3036M

七、nexus常用API

提供有丰富的REST 和 Integration API 可参考官方文档](https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api)) 或者本地部署的swagger