2014-11-23 2 views
1

UI에서 버튼을 누를 때마다 탄성 검색에 연결되고 쿼리가 실행되는 웹 서비스가 있습니다. 이것은 매번 실행되는 코드입니다. 문제는 잠시 후 간헐적으로 UI가 중단된다는 것입니다. 우리는 Tomcat 서버를 재시작 할 때마다elasticsearch에서 Threadlocals와 관련된 메모리 누수 관련 문제

private static final String CONFIG_CLUSTER_NAME = "cluster.name"; 

private static final String CLUSTER_NAME = "sample_es"; 
private static final String[] transportAddress = { 
    //Machine details 
}; 

private static final int transportPort = 9300; 

public static Client initClient(){ 
    settings = ImmutableSettings.settingsBuilder().put(CONFIG_CLUSTER_NAME, CLUSTER_NAME).build(); 

     Client client = new TransportClient(settings); 
     for (int i=0 ; i < transportAddress.length-1 ; i++){ 
      ((TransportClient)client).addTransportAddress(new InetSocketTransportAddress(transportAddress[i], transportPort)); 
     } 
     logger.info("TransportClient Created"); 
     return client; 
} 


public static int query(String query) throws Exception 
{ 
    Client client = null; 
    try{ 

      client = initClient(); 

      //Query search code 

    }catch(Exception e){ 
      e.printStackTrace(); 
    }finally{ 
     if(client != null){ 
      client.close(); 
      logger.info("TransportClient Closed"); 
     } 
    } 
     return result_count; 
} 

, 이것은 우리가 로그에보고 된 오류 메시지입니다. 어떻게 해결해야합니까?

[org.elasticsearch.common.util.concurrent.jsr166y.ThreadLocalRandom$1] (value 
[org.e[email protected]5838ce3e]) and a value of type 
[org.elasticsearch.common.util.concurrent.jsr166y.ThreadLocalRandom] (value 
[org[email protected]796c75b1]) but failed to remove it 
when the web application was stopped. This is very likely to create a memory leak. 

답변

1

이것은 실제 문제와 Elasticsearch 톰캣에 의해 관리되는 스레드 풀을 사용하지 않는 문제가 더 수 없을 수도 있습니다. 따라서 쿼리가 실행 된 후 Tomcat을 다시 시작할 때마다 에 메모리 누수가 있다고 생각합니다. 이것은 "관리되지 않는"스레드가 Tomcat에서 트리거하는 경우에 일반적입니다. 그렇게 말하면 프로필러를 실행 한 다음 스레드 및 리소스를 모니터링하여 자체 청소를 수행했는지 여부를 확인할 수 있습니다. 제대로 정리하지 않으면 Elasticsearch의 GitHub 저장소에서 문제를 만드는 것이 좋습니다.

클라이언트 생성과 관련하여 : 이 아니고은 클라이언트를 생성, 사용하고 버리는 것이 좋습니다. 시작할 때 할당하고 필요에 따라 지속적으로 재생성하지 않고 클라이언트를 재사용하십시오. 그런 다음 Tomcat을 중지 할 때 종료 훅을 추가하여 닫습니다. 또한 for (int i=0 ; i < transportAddress.length-1 ; i++)은 마지막 전송 주소를 건너 뜁니다. -1없이 i < transportAddress.length을 사용하십시오.

try (Client client = initClient()) { 
    // Query search code 
} 
catch (Exception e) { 
    logger.warning("An unexpected error occurred for the query: {}", 
        query, e); 
} 
+0

그것 때문에 무슨 일이 일어나고 :

관련없는 있지만, 모든 Elasticsearch ClientAutoCloseable을 구현 당신이 것을 일을 계속하기를 원한다면 당신이 그것을 를 자동 종료하는 코드를 단순화 할 수있는 의미 (자바 7에서 추가) 우리는 모든 쿼리에 대해 새 클라이언트를 만들고 닫습니다. [https://github.com/elasticsearch/elasticsearch/issues/283](https://github.com/elasticsearch/elasticsearch/issues/283) 하나의 연결로 영원히 해결할 수 있습니까? 몇 시간 동안 아무도 그것을 사용하지 않더라도 ES 연결은 계속 유지됩니까? 아니면 부실해 집니까? 그래서 내가 매번 만들고 닫는 이유입니다. –

+1

클라이언트를 열린 상태로 유지하는 것이 좋습니다. – pickypg