Elasticsearch Too many dynamicscript compilations 오류
오류
23-10-18 08:43:55.268 DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /item_index/_update/4200?refresh=false HTTP/
...
23-10-18 08:43:55.271 DEBUG org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 400 Bad Request[\r][\n]"
23-10-18 08:43:55.271 DEBUG org.apache.http.wire - http-outgoing-0 << "{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"failed to execute script"}],"type":"illegal_argument_exception","reason":"failed to execute script","caused_by":{"type":"general_script_exception","reason":"Failed to compile inline script ... using lang [painless]","caused_by":{"type":"circuit_breaking_exception","reason":"[script] Too many dynamic script compilations within, max: [150/5m]; please use indexed, or scripts with parameters instead; this limit can be changed by the [script.max_compilations_rate] setting","bytes_wanted":0,"bytes_limit":0,"durability":"TRANSIENT"}}},"status":400}"
원인
Elasticsearch에서 “Too many dynamic script compilations” 오류는 Elasticsearch의 동적 스크립트 컴파일 횟수가 초과되어 발생.
오류 코드
public void updateItemNativeQuery(UpdateItemEvent updateItemEvent) {
UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(updateItemEvent.getShopSeq()))
.withScriptType(ScriptType.INLINE)
.withScriptedUpsert(true)
.withScript(String.format("""
if (!ctx._source.containsKey('items') || ctx._source.items == null) {
ctx._source.items = [];
}
for (item in ctx._source.items) {
if (item.itemSeq == %d) {
item.itemName = '%s';
item.itemStatus = %s;
break;
}
}
""",
updateItemEvent.getItemSeq(), updateItemEvent.getItemName(), updateItemEvent.getItemStatus().getCode(),
updateItemEvent.getItemSeq(), updateItemEvent.getItemName(), updateItemEvent.getItemStatus().getCode()))
.build();
this.elasticsearchOperations.update(updateQuery, IndexCoordinates.of("item_index"));
}
해결방안
-
스크립트 컴파일 횟수 증가
GET /_cluster/settings?include_defaults=true ... "script": { "allowed_contexts": [], "max_compilations_rate": "150/5m", "cache": { "max_size": "3000", "expire": "0ms" }, "painless": { "regex": { "enabled": "limited", "limit-factor": "6" } }, "max_size_in_bytes": "65535", "allowed_types": [], "disable_max_compilations_rate": "false" }, ...
현재 default로 설정된 스크립트 수(max_compilations_rate)를 확인하고 증가시킬 수 있다.
하지만 이는 elasticsearch cluster의 성능에 영향을 미치기 때문에 신중히 결정해야 한다.
-
스크립트 캐싱
참고: https://www.elastic.co/guide/en/elasticsearch/reference/current/scripts-and-search-speed.html
-
파라미터 사용
파라미터 사용한 변경 코드
public void updateItemNativeQuery(UpdateItemEvent updateItemEvent) {
Map<String, Object> params = new HashMap<>();
params.put("itemSeq", updateItemEvent.getItemSeq());
params.put("itemName", updateItemEvent.getItemName());
params.put("itemStatus", updateItemEvent.getItemStatus().getCode());
UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(updateItemEvent.getShopSeq()))
.withScriptType(ScriptType.INLINE)
.withScriptedUpsert(true)
.withParams(params)
.withScript("""
if (!ctx._source.containsKey('items') || ctx._source.items == null) {
ctx._source.items = [];
}
for (item in ctx._source.items) {
if (item.itemSeq == params.itemSeq) {
item.itemName = params.itemName;
item.itemStatus = params.itemStatus;
break;
}
}
""")
.build();
this.elasticsearchOperations.update(updateQuery, IndexCoordinates.of("item_index"));
}
테스트
@Test
void updateItemNativeQuery() {
UpdateItemEvent updateItemEvent = UpdateItemEvent.builder()
.shopSeq(4008L)
.itemSeq(17026L)
.itemName("구로양념숯불치킨")
.itemStatus(ItemStatus.ON_SALE)
.build();
this.itemRepository.updateItemNativeQuery(updateItemEvent);
}
23-10-18 10:44:34.205 DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /item_index/_update/4008?refresh=false HTTP/1.1[\r][\n]"
...
23-10-18 10:44:34.205 DEBUG org.apache.http.wire - http-outgoing-0 >> "{"script":{"params":{"itemName":"...","itemStatus":"2","itemSeq":17026},"source":"boolean updated = false;\n\nif (!ctx._source.containsKey('items') || ctx._source.items == null) {\n ctx._source.items = [];\n}\n\nfor (item in ctx._source.items) {\n if (item.itemSeq == params.itemSeq) {\n item.itemName = params.itemName;\n item.itemStatus = params.itemStatus;\n updated = true;\n break;\n }\n}\n\nif(!updated) {\n\n ctx._source.items.add([\n \"itemSeq\": params.itemSeq,\n \"itemName\": params.itemName,\n \"itemStatus:\": params.itemStatus\n ]);\n}\n"},"scripted_upsert":true}"
...
23-10-18 10:44:34.224 DEBUG org.apache.http.headers - http-outgoing-0 << HTTP/1.1 200 OK
댓글남기기