Como depurar SegmentNotFoundException quando um problema é relatado no AEM 6.x

Este artigo ajuda você a entender como depurar SegmentNotFoundException quando um problema é relatado no AEM 6.x, revertendo para a última revisão válida do armazenamento de segmentos.

Descrição description

Ambiente

Experience Manager 6.x

Problema/Sintomas

O log de erros mostra uma exceção SegmentNotFound, como no exemplo a seguir:

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)

Resolução resolution

Etapas para resolver

Há duas abordagens para corrigir o problema e remover as inconsistências no repositório

Reverter para a última revisão válida do repositório de segmentos.

Primeiro,  use a ferramenta oak run, que é um jar executável[ 1] que contém tudo o que você precisa para uma instalação simples do Oak e para executar operações relacionadas ao oak.

O modo de verificação de execução do oak-run pode ser usado para determinar a última revisão válida de um armazenamento de segmento.  Isso pode ser usado para reverter manualmente um armazenamento de segmento corrompido para sua última revisão válida.

Cuidado: este processo reverterá os dados no sistema para um ponto no tempo anterior.  Se você quiser evitar a perda de alterações em seu sistema, tente a opção B abaixo.

Para executar a verificação e restauração:

  1. Baixe uma versão do oak-run que corresponda à sua versão principal do oak emhttps://mvnrepository.com/artifact/org.apache.jackrabbit/oak-run

  2. Para reverter um armazenamento de segmento corrompido para seu último bom estado, altere para o diretório de trabalho do CQ (aquele que contém a pasta crx-quickstartfolder) e faça backup de todos os arquivos no ./crx-quickstart/repository/segmentstore/.

  3. Execute a verificação de consistência.

    java -Xmx6000m -jar oak-run-*.jar check —bin=-1 /path/to/crx-quickstart/repository/segmentstore

    Ela faz uma pesquisa retroativa através das revisões até encontrar uma consistente:

    Procure a mensagem como indicado abaixo:

    code language-none
    main INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Found latest good revision afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880
    
  4. Reverter o repositório para esta revisão ao editar ./crx-quickstart/repository/segmentstore/journal.log e excluindo todas as linhas após a linha que contém a última revisão válida.

  5. Remover tudo ./crx-quickstart/repository/segmentstore/*.bak arquivos.

  6. Execute a limpeza de pontos de verificação para remover pontos de verificação órfãos usando o seguinte comando:

    code language-none
    java -Xmx6000m -jar oak-run-*.jar checkpoints /path/to/crx-quickstart/repository/segmentstore rm-unreferenced
    
  7. Por fim, compacte o repositório:

    java -Xmx6000m -jar oak-run-*.jar compact /path/to/crx-quickstart/repository/segmentstore/

Pode haver casos em que a verificação de execução do oak não encontre a revisão válida e obtemos "ConsistencyChecker - Nenhuma revisão válida encontrada" ao executar o comando de verificação.

Como corrigir corrupção ao encontrar "ConsistencyChecker - Nenhuma revisão válida encontrada" na verificação de consistência

Remover nós corrompidos manualmente.

Você pode fazer o seguinte em AEM, configurações TarMK sem FileDatastore configurado e situações em que a corrupção está nos binários.

Cuidado: o procedimento abaixo destina-se a usuários avançados.  Ao excluir os nós corrompidos, você precisa garantir que eles não sejam nós do sistema (como /home, /jcr:system etc) .  Se eles forem nós do sistema, você precisa garantir que possa restaurá-los.  Consulte a equipe de Atendimento ao cliente do AEM para obter assistência com as etapas documentadas aqui, caso não tenha certeza.

  1. Pare o AEM.

  2. Use o console de execução do Oak e carregue o script groovy childCount para identificar os nós corrompidos no armazenamento de segmentos:

    Carregue o shell do console do oak-run:

    code language-none
    java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
    

    Execute os dois comandos abaixo no shell para carregar o script e executá-lo:

    code language-none
    :load https://gist.githubusercontent.com/stillalex/e7067bcb86c89bef66c8/raw/d7a5a9b839c3bb0ae5840252022f871fd38374d3/childCount.groovy
    countNodes(session.workingNode)
    

    Isso resulta na seguinte saída indicando o caminho para os nós corrompidos:

    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
    

    Em alguns casos, o problema é vinculado a propriedades binárias e o script groovy childCount não consegue localizar nenhum nó corrompido.  Nesses casos, você pode usar o seguinte comando, que lerá os primeiros 1024 bytes para cada binário encontrado durante a travessia (observe que esse comando será mais lento e só deverá ser usado quando o comando acima não retornar os resultados esperados):

    code language-none
    countNodes(session.workingNode,true)
    
  3. Remova todos os nós corrompidos identificados listados na saída do último comando usando rmNodes.groovy
    Carregue o shell do console oak-run usando o comando abaixo:

    code language-none
    java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
    

    Carregue o script groovy:

    code language-none
    :load
    https://gist.githubusercontent.com/stillalex/43c49af065e3dd1fd5bf/raw/9e726a59f75b46e7b474f7ac763b0888d5a3f0c3/rmNode.groovy
    

    Execute o comando rmNode para remover o nó corrompido, substitua /path/to/corrupt/node pelo caminho para o nó corrompido que você precisa remover.

    code language-none
    rmNode(session, "/path/to/corrupt/node")
    

    onde o caminho do nó corrompido é o caminho obtido na etapa 2, por exemplo: "/content/dam/test.txt/jcr:content/renditions/original/jcr:content/"

    Observação: Ao usar o oak-run.jar versão 1.6.13 e superior, defina o parâmetro —read-write JVM do se você encontrar um erro como:

    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)
    
  4. Repita a etapa 3 para todos os nós encontrados na etapa 2

    O comando rmNode acima deve retornar verdadeiro para o caminho corrompido, o que significa que ele o excluiu. Verifique se esses três caminhos corrompidos foram excluídos executando novamente o comando rmNode nesses caminhos. A próxima execução deve retornar falso.
    Se você vir que os mesmos caminhos ainda estão no repositório, use a versão corrigida do jar de execução do oak, ou seja, oak-run-1.2.18-NPR-17596. Esta versão do jar ignora binários ilegíveis na compactação, substituindo-os por binários de 0 bytes e registrando a exceção e o caminho para o servidor. O repositório compactado resultante deve passar pela verificação oak-run e pelo script de contagem de nós, e você também deve ser capaz de compactá-lo novamente usando uma oak-run não corrigida.

  5. Execute uma limpeza de ponto de verificação listando pontos de verificação seguindo as etapas abaixo. Se houver mais de um ponto de verificação, limpe-os:

    code language-none
    nohup java -Xmx4096m -jar oak-run-1.2.18.jar checkpoints /app/AEM6/author/crx-quickstart/repository/segmentstore rm-allnohup.out
    
  6. Execute uma compactação offline. Caso não saiba como executar a compactação offline, consulte aqui.

  7. Inicie o servidor e aguarde a conclusão da indexação.

Causa

Uma SegmentNotFoundException no log de erros significa que um segmento não está mais presente, embora alguém aparentemente tente acessá-lo. Há aproximadamente três causas raiz diferentes para isso: o segmento foi removido por intervenção manual (por exemplo, rm -rf /), o segmento foi removido pela coleção de lixo de revisão ou o segmento não pode ser encontrado devido a algum erro no código.

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f