본문 바로가기

SearchDeveloper/ElasticSearch

[트러블슈팅] Too many dynamic script compilations within, max: [75/5m]

현상

새롭게 만든 엘라스틱서치 검색 API 를 개발, 스테이지 환경에서 테스트를 마치고 긴장되는 마음으로 운영에 배포를 했는데... 이럴수가 엄청난 에러들이 뚜두두두 쏟아지는게 아닌가

org.elasticsearch.transport.RemoteTransportException: [indices:data/read/search[phase/query]]Caused by: org.elasticsearch.script.GeneralScriptException: Failed to compile inline script [if(doc['name.keyword'].value.toLowerCase().contains('디스프')) return 1; return 0;] using lang [painless]    ...Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [script] Too many dynamic script compilations within, max: [75/5m];

원인

찾아보니 ElasticSearch 는 OOM 에 대비해 5분에 75개의 스크립트만 컴파일할 수 있도록 제한을 걸어놨었고, 난 이런식으로 검색 요청이 들어올 때마다 매번 다른 스크립트를 생성하고 있었다.

public static SortBuilder seedIncludeSortBuilder(String seed) {
    String sortScript = "if(doc['name.keyword'].value.toLowerCase().contains('" + seed.toLowerCase() + "')) return 1; return 0;";
    Map<String, Object> parameters = new HashMap<>();

    return SortBuilders
            .scriptSort(new Script(ScriptType.INLINE, "painless", sortScript, parameters), ScriptSortBuilder.ScriptSortType.NUMBER)
            .order(SortOrder.DESC);
}
if(doc['name.keyword'].value.toLowerCase().contains('삼성전자')) return 1; return 0;
if(doc['name.keyword'].value.toLowerCase().contains('르네상스')) return 1; return 0;
if(doc['name.keyword'].value.toLowerCase().contains('달력')) return 1; return 0;

해결

1. 분당 컴파일 수를 늘린다.

2. 스크립트를 정적으로 바꾼다.

 

1차 해결 - 분당 컴파일 수를 늘린다.

일단 당장 에러가 안나게 하기 위해 분당 컴파일 수를 증가시켰다.

PUT _cluster/settings
{  "transient": {"script.max_compilations_rate":"100000/1m"  }}

1분에 10만개 까지 가능하도록 변경

gc

참고로 이 때 gc 부하가 빈번하게 일어난다는 로그가 뜬다.

 

2차 해결 - 스크립트를 정적으로 바꾼다.

매번 바뀌는 부분은 파라미터로 빼면 항상 같은 스크립트를 쓸 수 있다.

public static SortBuilder seedIncludeSortBuilder(String seed) {
    String sortScript = "if(doc['name.keyword'].value.toLowerCase().contains(params.seed)) return 1; return 0;";
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("seed", seed.toLowerCase());

    return SortBuilders
            .scriptSort(new Script(ScriptType.INLINE, "painless", sortScript, parameters), ScriptSortBuilder.ScriptSortType.NUMBER)
            .order(SortOrder.DESC);
}

 

레퍼런스

https://wedul.site/655

글 읽어주셔서 언제나 감사합니다. 좋은 피드백, 개선 피드백 너무나도 환영합니다.

 

[트러블슈팅] Too many dynamic script compilations within, max: [75/5m]