AEM 6.x에서 문제가 보고될 때 SegmentNotFoundException을 디버깅하는 방법
이 문서는 마지막으로 알려진 세그먼트 스토어 수정 버전으로 되돌려 AEM 6.x에서 문제가 보고될 때 SegmentNotFoundException을 디버깅하는 방법을 이해하는 데 도움이 됩니다.
설명 description
환경
Experience Manager 6.x
문제/증상
오류 로그는 다음 예제와 같이 SegmentNotFound 예외를 표시합니다.
org.apache.jackrabbit.oak.segment.SegmentNotFoundException: Segment d2c720c4-c146-4ab1-ac37-542aad93c33f not found at
org.apache.jackrabbit.oak.segment.file.FileStore$8.call(FileStore.java:602) at
org.apache.jackrabbit.oak.segment.file.FileStore$8.call(FileStore.java:542) at
org.apache.jackrabbit.oak.segment.SegmentCache.getSegment(SegmentCache.java:95) at
org.apache.jackrabbit.oak.segment.file.FileStore.readSegment(FileStore.java:542) at
org.apache.jackrabbit.oak.segment.SegmentId.getSegment(SegmentId.java:125) at
org.apache.jackrabbit.oak.segment.Record.getSegment(Record.java:70) at
org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:424) at
org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:433) at
org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:391) at
org.apache.jackrabbit.oak.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:608) at
org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148) at
org.apache.jackrabbit.oak.segment.MapRecord$3.childNodeChanged(MapRecord.java:442) at
org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:490) at
org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:433) at
org.apache.jackrabbit.oak.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:608) at
org.apache.jackrabbit.oak.spi.commit.EditorDiff.process(EditorDiff.java:52) at
org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.updateIndex(AsyncIndexUpdate.java:695) at
org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.runWhenPermitted(AsyncIndexUpdate.java:543) at
org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.run(AsyncIndexUpdate.java:402) at
org.apache.sling.commons.scheduler.impl.QuartzJobExecutor.execute(QuartzJobExecutor.java:118) at
org.quartz.core.JobRunShell.run(JobRunShell.java:202) at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at
java.lang.Thread.run(Thread.java:745)
해결 방법 resolution
해결 단계
두 가지 방법으로 문제를 해결하고 저장소에서 불일치를 제거할 수 있습니다
마지막으로 알려진 세그먼트 저장소 수정 버전으로 되돌리기.
첫 번째, oak 실행 도구를 사용하십시오. 이 도구는 간단한 Oak 설치 및 oak 관련 작업 수행에 필요한 모든 것을 포함하는 실행 가능한 jar [ 1]입니다.
oak-run의 점검 실행 모드를 사용하여 마지막으로 알려진 세그먼트 스토어 수정을 확인할 수 있습니다. 수동으로 손상된 세그먼트 스토어를 최신 버전으로 되돌리는 데 사용할 수 있습니다.
주의: 이 프로세스는 시스템의 데이터를 이전 시점으로 롤백합니다. 시스템에서 변경 사항의 손실을 방지하려면 대신 아래 옵션 B를 시도할 수 있습니다.
확인 및 복원하려면
-
https://mvnrepository.com/artifact/org.apache.jackrabbit/oak-run에서 Oak 코어 버전과 일치하는 oak-run 버전을 다운로드합니다.
-
손상된 세그먼트 저장소를 양호한 최신 상태로 되돌리려면 CQ의 작업 디렉터리(crx-quickstartfolder가 포함된 디렉터리)로 변경하고 의 모든 파일을 백업합니다./crx-quickstart/repository/segmentstore/
-
일관성 검사를 실행하고
java -Xmx6000m -jar oak-run-*.jar check —bin=-1 /path/to/crx-quickstart/repository/segmentstore
일관된 버전을 찾을 때까지 수정 버전을 뒤로 검색합니다.
다음과 같이 메시지를 검색합니다.
code language-none main INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Found latest good revision afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880 -
를 편집하여 저장소를 이 수정 버전으로 되돌립니다./crx-quickstart/repository/segmentstore/journal.log 및 최신 수정 버전이 포함된 줄 다음의 모든 줄을 삭제합니다.
-
모두 제거 ./crx-quickstart/repository/segmentstore/*.bak 파일.
-
다음 명령을 사용하여 체크포인트 정리를 실행하여 고립된 체크포인트를 제거합니다.
code language-none java -Xmx6000m -jar oak-run-*.jar checkpoints /path/to/crx-quickstart/repository/segmentstore rm-unreferenced -
마지막으로 저장소 압축:
java -Xmx6000m -jar oak-run-*.jar compact /path/to/crx-quickstart/repository/segmentstore/
Check 명령을 실행하는 동안 oak 실행 검사에서 올바른 수정 버전을 찾을 수 없고 "ConsistencyChecker - 올바른 수정 버전이 없습니다"가 표시되는 경우가 있습니다.
일관성 검사에서 "ConsistencyChecker - 좋은 수정 버전을 찾을 수 없음"이 발생할 때 손상을 해결하는 방법
수동으로 손상된 노드 제거.
AEM, FileDatastore가 구성되지 않은 TarMK 설정 및 바이너리에 손상이 있는 상황에서 다음 작업을 수행할 수 있습니다.
주의: 아래 절차는 고급 사용자를 위한 것입니다. 손상된 노드를 삭제할 때 시스템 노드가 아닌지 확인해야 합니다(예: /home, /jcr:system 등). 시스템 노드인 경우 복원할 수 있는지 확인해야 합니다. 잘 모르는 경우 여기에 설명된 단계에 도움이 필요하면 AEM 고객 지원 센터에 문의하십시오.
-
AEM을 중지합니다.
-
Oak 실행 콘솔을 사용하고 childCount groovy 스크립트를 로드하여 세그먼트 스토어에서 손상된 노드를 식별합니다.
oak-run 콘솔 셸 로드:
code language-none java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore셸에서 아래 두 명령을 실행하여 스크립트를 로드하고 실행합니다.
code language-none :load https://gist.githubusercontent.com/stillalex/e7067bcb86c89bef66c8/raw/d7a5a9b839c3bb0ae5840252022f871fd38374d3/childCount.groovy countNodes(session.workingNode)이로 인해 손상된 노드의 경로를 나타내는 다음과 같은 출력이 발생합니다.
code language-none 21:21:42.029 main ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 63ae05a4-b506-445c-baa2-cfa1b13b6e2f. Creation date delta is 3 ms. warning unable to read node /content/dam/test.txt/jcr:content/renditions/original/jcr:content문제가 이진 속성에 연결되고 childCount groovy 스크립트가 손상된 노드를 찾을 수 없는 경우가 있습니다. 이러한 경우 대신 다음 명령을 사용할 수 있습니다. 이 명령은 순회 중에 발견된 모든 바이너리의 처음 1,024바이트를 읽습니다(이 명령은 속도가 느려지고 위의 명령이 예상 결과를 반환하지 않을 때만 사용해야 함).
code language-none countNodes(session.workingNode,true) -
rmNodes.groovy를 사용하여 마지막 명령의 출력에 나열된 식별된 손상 노드를 모두 제거합니다.
아래 명령을 사용하여 oak-run 콘솔 셸을 로드합니다.code language-none java -jar oak-run-*.jar console crx-quickstart/repository/segmentstoreGroovy 스크립트 로드:
code language-none :load https://gist.githubusercontent.com/stillalex/43c49af065e3dd1fd5bf/raw/9e726a59f75b46e7b474f7ac763b0888d5a3f0c3/rmNode.groovyrmNode 명령을 실행하여 손상된 노드를 제거하고 /path/to/corrupt/node 를 제거해야 하는 손상된 노드에 대한 경로로 바꿉니다.
code language-none rmNode(session, "/path/to/corrupt/node")손상 노드 경로가 2단계에 얻은 경로인 경우, 예: "/content/dam/test.txt/jcr:content/renditions/original/jcr:content/"
참고: oak-run.jar 버전 1.6.13 이상을 사용할 때 다음과 같은 오류가 발생하는 경우 —read-write JVM 매개변수를 설정합니다.
code language-none / rmNode(session,"/path/to/corrupt/node") Removing node /path/to/corrupt/node ERROR java.lang.UnsupportedOperationException: Cannot write to read-only store at org.apache.jackrabbit.oak.segment.SegmentWriterBuilder$1.execute (SegmentWriterBuilder.java:171) at org.apache.jackrabbit.oak.segment.SegmentWriter.writeNode (SegmentWriter.java:318) at org.apache.jackrabbit.oak.segment.SegmentNodeBuilder.getNodeState (SegmentNodeBuilder.java:111) at org.apache.jackrabbit.oak.segment.SegmentNodeStore$Commit.init (SegmentNodeStore.java:581) at org.apache.jackrabbit.oak.segment.SegmentNodeStore.merge (SegmentNodeStore.java:333) at org.apache.jackrabbit.oak.spi.state.NodeStore$merge.call (Unknown Source) at groovysh_evaluate.rmNode (groovysh_evaluate:11) -
2단계에서 찾은 모든 노드에 대해 3단계를 반복합니다
위의 rmNode 명령은 삭제된 손상 경로에 대해 true를 반환해야 합니다. 발견된 세 개의 손상 경로는 해당 경로의 rmNode 명령을 다시 실행하여 삭제해야 합니다. false를 반환하는 경우 실행합니다.
동일한 경로가 저장소에 계속 존재하는 경우 oak-run jar, 즉 oak-run-1.2.18-NPR-17596 의 패치 버전을 사용하십시오. 이 버전의 jar는 압축 시 읽을 수 없는 바이너리를 건너뛰고 0바이트 바이너리로 바꾸고 예외 및 syserr 경로를 기록합니다. 압축한 결과 저장소는 oak-run 점검 및 노드 수 스크립트를 통과하고, 패치되지 않은 oak-run을 사용하여 다시 압축할 수도 있어야 합니다. -
아래 체크포인트를 나열하여 체크포인트 정리를 수행합니다. 체크포인트가 두 개 이상인 경우 정리합니다.
code language-none nohup java -Xmx4096m -jar oak-run-1.2.18.jar checkpoints /app/AEM6/author/crx-quickstart/repository/segmentstore rm-allnohup.out -
오프라인 압축을 실행합니다. 오프라인 압축을 실행하는 방법을 모를 경우 여기를 참조하십시오.
-
인덱싱이 완료될 때까지 서버를 시작합니다.
원인
오류 로그에 있는 SegmentNotFoundException은 다른 사용자가 해당 세그먼트에 계속 액세스하려고 하지만 해당 세그먼트가 더 이상 존재하지 않음을 의미합니다. 여기에는 크게 세 가지 다른 근본 원인이 있습니다. 수동 개입으로 세그먼트가 제거되었거나(예: rm -rf /), 수정 가비지 수집으로 세그먼트가 제거되었거나, 코드의 일부 버그로 인해 세그먼트를 찾을 수 없습니다.