Nexus 시작시 NullPointException 이 발생하면서 오류가 나는 현상
현재 외부 Nexus Repository에서 내부 Nexus Repository에 복제 처리를 하고 있습니다. Nexus에서 갑자기 오류가 발생했습니다. 그냥 재부팅을 했을 뿐인데 오류가 발생하였다고 합니다. 해당 내역이 이미 nexus의 팁에 올라와 있어서 따라해보니, 복구가 문제 없이 되었습니다.
문제
Nexus3을 빠르게 중지했다가 다시 시작하면 Nexus3 리포지토리가 전혀 시작되지 않을 수 있으며 로깅에 다음과 같은 예외가 발생할 수 있습니다
2023-08-11 09:50:14,365+0900 INFO [FelixStartLevel] *SYSTEM org.sonatype.nexus.pax.logging.NexusLogActivator - start
2023-08-11 09:50:14,790+0900 INFO [FelixStartLevel] *SYSTEM org.sonatype.nexus.features.internal.FeaturesWrapper - Fast FeaturesService starting
2023-08-11 09:50:14,845+0900 ERROR [FelixStartLevel] *SYSTEM org.apache.karaf.deployer.features.FeatureDeploymentListener - Unable to update deployed features for bundle: org.apache.felix.framework - 6.0.5
java.lang.NullPointerException: null
at org.apache.karaf.deployer.features.FeatureDeploymentListener.bundleChanged(FeatureDeploymentListener.java:254)
at org.apache.karaf.deployer.features.FeatureDeploymentListener.init(FeatureDeploymentListener.java:90)
at org.apache.karaf.deployer.features.osgi.Activator$DeploymentFinishedListener.deploymentEvent(Activator.java:86)
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.registerListener(FeaturesServiceImpl.java:296)
at org.apache.karaf.deployer.features.osgi.Activator.doStart(Activator.java:53)
at org.apache.karaf.util.tracker.BaseActivator.start(BaseActivator.java:92)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:698)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2402)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2308)
at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1539)
at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
at java.lang.Thread.run(Thread.java:748)
2023-08-11 09:50:14,847+0900 ERROR [FelixStartLevel] *SYSTEM org.apache.karaf.deployer.features.FeatureDeploymentListener - Unable to update deployed features for bundle: org.apache.karaf.features.extension - 4.3.6
java.lang.NullPointerException: null
at org.apache.karaf.deployer.features.FeatureDeploymentListener.bundleChanged(FeatureDeploymentListener.java:254)
at org.apache.karaf.deployer.features.FeatureDeploymentListener.init(FeatureDeploymentListener.java:90)
at org.apache.karaf.deployer.features.osgi.Activator$DeploymentFinishedListener.deploymentEvent(Activator.java:86)
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.registerListener(FeaturesServiceImpl.java:296)
at org.apache.karaf.deployer.features.osgi.Activator.doStart(Activator.java:53)
at org.apache.karaf.util.tracker.BaseActivator.start(BaseActivator.java:92)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:698)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2402)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2308)
at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1539)
at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
at java.lang.Thread.run(Thread.java:748)
원인
- 이 문제는 시스템이 빠르게 재시작된 후(systemd를 통해 Nexus 리포지토리가 자동으로 시작되는 경우) 자주 관찰되었습니다.
- 이 오류는 부팅 시퀀스가 시작될 때 바로 발생합니다.
- 문제 발생 시 캡처된 로깅 또는 스레드 덤프에는 문제가 어디에 있는지 알 수 있는 힌트가 없습니다.
해결 방법 - Race condition between the FeaturesService and FeatureDeploymentListener
손상된 파일을 찾기 위한 명령어
# 설치 위치와 버젼 정보를 변경
_VER="3.38.0-01";
_INSTALL_DIR="/application/nexus-${_VER}";
cd $(dirname ${_INSTALL_DIR%/});
curl -o "/tmp/nexus-unix.tar.gz" -L "https://download.sonatype.com/nexus/3/nexus-${_VER}-unix.tar.gz";
tar --diff -f "/tmp/nexus-unix.tar.gz" nexus-${_VER}/etc/karaf | grep -vE '(Uid|Gid|Mod time) differs'
“karaf” 디렉터리 아래의 모든 파일을 복원하는 명령의 예입니다
cd $(dirname ${_INSTALL_DIR%/});
tar -xv -f "/tmp/nexus-unix.tar.gz" nexus-${_VER}/etc/karaf
가능한 원인
마운트된 디스크(넥서스 리포지토리 관련)가 충분히 빨리 마운트되지 않거나 ‘systemd’가 시작되기 전에 네트워크가 완전히 초기화 및 가동되지 않아 발생할 수 있습니다.
만약, 네트워크 마운트에 의존하는 경우 Nexus 리포지토리 서비스가 시작되기 전에 네트워크 마운트를 완전히 사용할 수 있는지 확인하면 이 문제를 해결할 수 있습니다.
- 의존하는 마운트를 설정합니다(블롭 스토어 또는 Nexus 리포지토리 데이터 중 하나).
- 실행
systemctl list-units | grep '.mount'
- 마운트 ‘단위’의 이름을 가져옵니다.
- 서비스 [단위] 섹션 옵션에 네트워크와 마운트를 모두 추가하고
Requires
및After
를 선택합니다.[Unit] ... Requires=network.target network-online.target <required mount 1>.mount <required mount2>.mount multi-user.target After=network.target network-online.target <required mount 1>.mount <required mount2>.mount multi-user.target