Circuit break the number of inline scripts compiled per minute#19694
Circuit break the number of inline scripts compiled per minute#19694dakrone merged 1 commit intoelastic:masterfrom
Conversation
|
As something to think about for this:
|
|
I think I'd prefer a warning. I'm fairly sure I'd have noticed it when running Elasticsearch. |
There was a problem hiding this comment.
It'd be useful to describe the how here I think. I guess this works like a bucket of water slowly filling up. You get to compile a script if there is enough water in the bucket, otherwise you don't. If the bucket overflows then you don't get more water.
There was a problem hiding this comment.
Yeah, it's a variant of the token bucket algorithm
There was a problem hiding this comment.
Yeah, that link'd be a lovely comment.
|
I think people won't notice it unless it is an exception, just like all the other safeguards. The immediate workaround for the user is to update a dynamic setting, giving them time to update their application. I think the default limit should be lower so that a user is more likely to trip this safeguard in dev instead of production. |
Okay, I originally went with 10 a minute (before going for 30/min for this PR), does that sound reasonable or too low/high? |
|
So one compilation every 6 seconds. That seems OK, even during script development. Maybe a tiny bit tight. 15 would definitely be ok though |
|
Okay, I pushed a new commit that sets the limit to 15/min |
There was a problem hiding this comment.
Maybe something like: The bucket can "overflow", in which case the excess capacity is just "spilled", rather than saved up. So it never holds more than a minute's capacity.
There was a problem hiding this comment.
Definitely, I will add that
|
I looked at this again with new eyes this morning and left a few comments, mostly about funky side cases like "what if I set this to Long.MAX_VALUE?", "What if I set this to 0?" and "What if I set this to -123?". |
|
@nik9000 okay I pushed a bunch of commits that I tried to break into meaningful pieces with nice commit messages, addressing your concerns :) |
There was a problem hiding this comment.
You might want to save the value of the limit rather than do it every iteration?
|
Left a small question/suggestion. Otherwise LGTM. Feel free to address my last point however you like and merge when you have a chance. |
When compiling many dynamically changing scripts, parameterized scripts (<https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting-using.html#prefer-params>) should be preferred. This enforces a limit to the number of scripts that can be compiled within a minute. A new dynamic setting is added - `script.max_compilations_per_minute`, which defaults to 15. If more dynamic scripts are sent, a user will get the following exception: ```json { "error" : { "root_cause" : [ { "type" : "circuit_breaking_exception", "reason" : "[script] Too many dynamic script compilations within one minute, max: [15/min]; please use on-disk, indexed, or scripts with parameters instead", "bytes_wanted" : 0, "bytes_limit" : 0 } ], "type" : "search_phase_execution_exception", "reason" : "all shards failed", "phase" : "query", "grouped" : true, "failed_shards" : [ { "shard" : 0, "index" : "i", "node" : "a5V1eXcZRYiIk8lecjZ4Jw", "reason" : { "type" : "general_script_exception", "reason" : "Failed to compile inline script [\"aaaaaaaaaaaaaaaa\"] using lang [painless]", "caused_by" : { "type" : "circuit_breaking_exception", "reason" : "[script] Too many dynamic script compilations within one minute, max: [15/min]; please use on-disk, indexed, or scripts with parameters instead", "bytes_wanted" : 0, "bytes_limit" : 0 } } } ], "caused_by" : { "type" : "general_script_exception", "reason" : "Failed to compile inline script [\"aaaaaaaaaaaaaaaa\"] using lang [painless]", "caused_by" : { "type" : "circuit_breaking_exception", "reason" : "[script] Too many dynamic script compilations within one minute, max: [15/min]; please use on-disk, indexed, or scripts with parameters instead", "bytes_wanted" : 0, "bytes_limit" : 0 } } }, "status" : 500 } ``` This also fixes a bug in `ScriptService` where requests being executed concurrently on a single node could cause a script to be compiled multiple times (many in the case of a powerful node with many shards) due to no synchronization between checking the cache and compiling the script. There is now synchronization so that a script being compiled will only be compiled once regardless of the number of concurrent searches on a node. Relates to elastic#19396
700a4bb to
2be52ef
Compare
When compiling many dynamically changing scripts, parameterized
scripts (https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting-using.html#prefer-params)
should be preferred. This enforces a limit to the number of scripts that
can be compiled within a minute. A new dynamic setting is added -
script.max_compilations_per_minute, which defaults to 15.If more dynamic scripts are sent, a user will get the following
exception:
{ "error" : { "root_cause" : [ { "type" : "circuit_breaking_exception", "reason" : "[script] Too many dynamic script compilations within one minute, max: [30/min]; please use on-disk, indexed, or scripts with parameters instead", "bytes_wanted" : 0, "bytes_limit" : 0 } ], "type" : "search_phase_execution_exception", "reason" : "all shards failed", "phase" : "query", "grouped" : true, "failed_shards" : [ { "shard" : 0, "index" : "i", "node" : "a5V1eXcZRYiIk8lecjZ4Jw", "reason" : { "type" : "general_script_exception", "reason" : "Failed to compile inline script [\"aaaaaaaaaaaaaaaa\"] using lang [painless]", "caused_by" : { "type" : "circuit_breaking_exception", "reason" : "[script] Too many dynamic script compilations within one minute, max: [30/min]; please use on-disk, indexed, or scripts with parameters instead", "bytes_wanted" : 0, "bytes_limit" : 0 } } } ], "caused_by" : { "type" : "general_script_exception", "reason" : "Failed to compile inline script [\"aaaaaaaaaaaaaaaa\"] using lang [painless]", "caused_by" : { "type" : "circuit_breaking_exception", "reason" : "[script] Too many dynamic script compilations within one minute, max: [30/min]; please use on-disk, indexed, or scripts with parameters instead", "bytes_wanted" : 0, "bytes_limit" : 0 } } }, "status" : 500 }This also fixes a bug in
ScriptServicewhere requests being executedconcurrently on a single node could cause a script to be compiled
multiple times (many in the case of a powerful node with many shards)
due to no synchronization between checking the cache and compiling the
script. There is now synchronization so that a script being compiled
will only be compiled once regardless of the number of concurrent
searches on a node.
Relates to #19396