본문 바로가기

Java

OpenSearch를 사용하면서 발생한 문제

1. Error: java.net.SocketTimeoutException: 30,000 milliseconds timeout on connection http-outgoing-2 [ACTIVE]

에러 상황

  • OpenSearch에 data를 insert 후 default timeout 값인 30초를 넘었기 때문에 TimeOut 발생

 

원인

  • 클라이언트에서 Connection 종료를 인지하지 못하고 계속 연결되어 있다가 lost connection으로 시

 

해결 방법

@Configuration
public class OpensearchInit {
	@Value("${opensearch.ip}")
	private String hostIp;
	@Value("${opensearch.port}")
	private int hostPort;
	@Value("${opensearch.protocol}")
	private String protocol;
	private final int SET_TIME_OUT = 1000 * 40;

	@Bean
	public RestHighLevelClient restHighLevelClient() {
		return new RestHighLevelClient(
			RestClient.builder(new HttpHost(this.hostIp, this.hostPort, this.protocol))
				.setRequestConfigCallback(c -> {
					c.setConnectTimeout(SET_TIME_OUT);
					c.setSocketTimeout(SET_TIME_OUT);
					return c;
				}
			)
		);
	}
}
  • OpenSearch 객체를 생성할 때 Connection Timeout, SocketTimeout 시간을 변경한다.

 

 

2. Error: OpenSearchStatusException[OpenSearch exception [type=circuit_breaking_exception, reason=[parent] Data too large, data for [<http_request>]

에러 상황

  • OpenSearch에 circuit_breaking_exception 발생

 

원인

  • circuit_breaking_exception : OpenSearch가 제한된 메모리 용량 안에서 데이터 처리를 하기 위해 circuit breaker를 사용하는데,이를 통해 지정된 한계를 초과하면 작업을 중지한 에러

 

 

해결 방법

  • OpenSearch 의  힙 메모리 크기를 수정하는 방법이다.
  • OpenSearch의 config 파일 중 jvm.options을 수정한다
  • Xms은 최소, Xmx는 최대를 의미하며 Xms1g -> Xms30G, Xmx1g -> xmx30G로 변경
  • 힙 크기를 30GB로 변경하였는데 Java Application에서 너무 작은 힙 크기는 OOM(Out-Of-Memoery Exception)을 발생시키고, 너무 큰 힙 크기는 시스템 전체가 마비되는 STM를 발생시킨다.
  • 일반적인 상황에서는 엘라스틱서치(오픈서치)에 설정된 힙의 크기가 클수록 좋습니다. 하지만 그렇- 다고해서 무작정 큰 메모리를 할당하는 것은 성능에 심각한 문제를 야기시킬 수 있습니다. 엘라스틱서치에서는 할당할 힙 크기의 최대값으로 32GB 이하를 설정하도록 권장합니다.

 

 

3. Error: Exception in thread "Thread-35" java.lang.OutOfMemoryError: Java heap space

에러 상황

  • JVM에서 힙 메모리 초과
  • 해당 에러는 프로그램이 필요한 만큼의 메모리를 할당 받지 못해 발생

 

원인

  • 데이터 처리량이 많아서 메모리 소모하는 경우
  • 무한 루프타 재귀호출로 인해 메모리를 무한정 소모

 

해결 방법

  • 보통 무한 루프나 재귀 호출로 인한 메모리 무한정 소모가 주요 원인이므로 해당 에러가 난 로직을 분석 후 수정한다.

 

 

4. Error: Result window is too large, from + size must be less than or equlas to : [10000] but was [10001]

에러 상황

  • OpenSearch에서 조회 시 from + size의 합이 10000을 넘어서 발생한 오류

 

원인

  • OpenSearch에서 검색할 수 있는 최대 document는 default로 10000개로 되어 있다. 이때, 그 이상을 조회할 때 발생한다.

 

해결 방법

  1. index.max_result_window 사이즈 변경하기
PUT index_name/_settings {
	"max_result_window" : [크기]
}
  • OpenSearch의 default 값인 10000보다 크게 변경
  • 하지만 이것은 과도한 리소스 사용으로 성능 문제를 야기
  1. Bulk API 사용
GET index_name/_search?scroll=1m
{
	"size" : 10000
}
  • 해당 API를 사용한다고 해서 10000 이상 검색할 수 있는 것은 아니지만 조회한 값 이후 존재하는 값을 이어서 조회할 수 있다.
POST /_search/scroll {
	"scroll" : "1m"
	"scroll_id : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFkhFaXNwUDY2VDFtbVl0S
mVsUXd6S1EAAAAAAAAA4hZ6ako2TUlKV1R3Q2hsaFBPUk1yam9B"
}

  • Bulk API를 통해 조회 후 _scroll_id 값과 /_search/scroll API를 사용해 조회할 경우 처음 조회한 결과 값 이후 값을 조회할 수 있다.

 

5. 조회 문제

PUT info/_doc/{1,2,3,4} 
{  "address": [    {      
      "city": "busan",      
      "district": "bukgu",      
      "detail": "hwamyeong1dong"    
   },    
   {      
      "city": "busan",      
      "district": "bukgu",      
      "detail": "hwamyeong2dong"    
   },    
   {   
      "city": "busan",      
      "district": "bukgu",      
      "detail": "hwamyeong3dong"    
   },    
   {      
     "city": "busan",      
     "district": "bukgu",      
     "detail": "hwamyeong"    
   }      
]}
GET info/_search
{  
   "query":{    
      "match": {      
         "address.detail.keyword": "hwamyeong"    
       }  
   }
}

쿼리 결과

 

문제 상황

  • document 1,2,3,4 에 각각 해당 value값을 넣은 후 address 값이 hwamyeong 인 것을 검색했지만 일치하지 않은 값이 출력된 상황

 

원인

  • address의 type은 Object이고 Object 중 하나의 값이 일치하여 해당 Object 전체 값이 출력된 상황

 

해결 방법

  • 객체의 mapping 정보를 Nest Type으로 변경
  • “type” : “nested” 추가

 

위와 같이 객체의 mapping 정보를 변경할 경우 기존에 사용하던 검색 방식을 사용할 수 없다.

GET info/_search
{  
   "query": {    
      "nested": {      
         "path": "address",        
            "query": {          
               "wildcard": {            
                  "address.detail.keyword": "hwamyeong“
               }
            },
          "inner_hits": {}    
       }  
   }
}
  • 기존 search query 방식에서 nested를 추가해서 조회해야 한다.

 

쿼리 결과

  • inner_hist에 있는 값이 nested로 조회된 결과 값이다.
  • 조회 결과를 보면 결국 Object로 조회한 결과 값까지 출력된 점이 문제다.

 

_source 추가

GET info/_search
{  
   "query": {    
      "nested": {      
         "path": "address",        
            "query": {          
               "wildcard": {            
                  "address.detail.keyword": "hwamyeong“
               }
            },
          "inner_hits": {}    
       }  
   } ,"_source": "inner_hits"
}
  • _source 를 사용하여 inner_hist만 결과 값에 출력하여 원하는 값만 결과에 나오도록 한다.