Skip to content

Commit 3d53dae

Browse files
Account for XContent overhead in in-flight breaker
So far the in-flight request circuit breaker has only accounted for the on-the-wire representation of a request. However, we convert the raw request into XContent internally which increases the overhead. Therefore, we increase the value of the corresponding setting `network.breaker.inflight_requests.overhead` from one to two. While this value is still rather conservative (we assume that the representation as structured objects has no overhead compared to the byte[]), it is closer to reality than the current value. Relates #31613
1 parent ee4dbc8 commit 3d53dae

File tree

4 files changed

+19
-11
lines changed

4 files changed

+19
-11
lines changed

docs/reference/migration/migrate_7_0/indices.asciidoc

+6
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,9 @@ The following previously deprecated url parameter have been removed:
6464
* `filter_cache` - use `query` instead
6565
* `request_cache` - use `request` instead
6666
* `field_data` - use `fielddata` instead
67+
68+
==== `network.breaker.inflight_requests.overhead` increased to 2
69+
70+
Previously the in flight requests circuit breaker considered only the raw byte representation.
71+
By bumping the value of `network.breaker.inflight_requests.overhead` from 1 to 2, this circuit
72+
breaker considers now also the memory overhead of representing the request as a structured object.

docs/reference/modules/indices/circuit_breaker.asciidoc

+4-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ request) from exceeding a certain amount of memory.
6060

6161
The in flight requests circuit breaker allows Elasticsearch to limit the memory usage of all
6262
currently active incoming requests on transport or HTTP level from exceeding a certain amount of
63-
memory on a node. The memory usage is based on the content length of the request itself.
63+
memory on a node. The memory usage is based on the content length of the request itself. This
64+
circuit breaker also considers that memory is not only needed for representing the raw request but
65+
also as a structured object which is reflected by default overhead.
6466

6567
`network.breaker.inflight_requests.limit`::
6668

@@ -70,7 +72,7 @@ memory on a node. The memory usage is based on the content length of the request
7072
`network.breaker.inflight_requests.overhead`::
7173

7274
A constant that all in flight requests estimations are multiplied with to determine a
73-
final estimation. Defaults to 1
75+
final estimation. Defaults to 2.
7476

7577
[[accounting-circuit-breaker]]
7678
[float]

server/src/main/java/org/elasticsearch/indices/breaker/HierarchyCircuitBreakerService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public class HierarchyCircuitBreakerService extends CircuitBreakerService {
7373
public static final Setting<ByteSizeValue> IN_FLIGHT_REQUESTS_CIRCUIT_BREAKER_LIMIT_SETTING =
7474
Setting.memorySizeSetting("network.breaker.inflight_requests.limit", "100%", Property.Dynamic, Property.NodeScope);
7575
public static final Setting<Double> IN_FLIGHT_REQUESTS_CIRCUIT_BREAKER_OVERHEAD_SETTING =
76-
Setting.doubleSetting("network.breaker.inflight_requests.overhead", 1.0d, 0.0d, Property.Dynamic, Property.NodeScope);
76+
Setting.doubleSetting("network.breaker.inflight_requests.overhead", 2.0d, 0.0d, Property.Dynamic, Property.NodeScope);
7777
public static final Setting<CircuitBreaker.Type> IN_FLIGHT_REQUESTS_CIRCUIT_BREAKER_TYPE_SETTING =
7878
new Setting<>("network.breaker.inflight_requests.type", "memory", CircuitBreaker.Type::parseValue, Property.NodeScope);
7979

server/src/test/java/org/elasticsearch/rest/RestControllerTests.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ public boolean canTripCircuitBreaker() {
239239

240240
public void testDispatchRequestAddsAndFreesBytesOnSuccess() {
241241
int contentLength = BREAKER_LIMIT.bytesAsInt();
242-
String content = randomAlphaOfLength(contentLength);
242+
String content = randomAlphaOfLength((int) Math.round(contentLength / inFlightRequestsBreaker.getOverhead()));
243243
RestRequest request = testRestRequest("/", content, XContentType.JSON);
244244
AssertingChannel channel = new AssertingChannel(request, true, RestStatus.OK);
245245

@@ -251,7 +251,7 @@ public void testDispatchRequestAddsAndFreesBytesOnSuccess() {
251251

252252
public void testDispatchRequestAddsAndFreesBytesOnError() {
253253
int contentLength = BREAKER_LIMIT.bytesAsInt();
254-
String content = randomAlphaOfLength(contentLength);
254+
String content = randomAlphaOfLength((int) Math.round(contentLength / inFlightRequestsBreaker.getOverhead()));
255255
RestRequest request = testRestRequest("/error", content, XContentType.JSON);
256256
AssertingChannel channel = new AssertingChannel(request, true, RestStatus.BAD_REQUEST);
257257

@@ -263,7 +263,7 @@ public void testDispatchRequestAddsAndFreesBytesOnError() {
263263

264264
public void testDispatchRequestAddsAndFreesBytesOnlyOnceOnError() {
265265
int contentLength = BREAKER_LIMIT.bytesAsInt();
266-
String content = randomAlphaOfLength(contentLength);
266+
String content = randomAlphaOfLength((int) Math.round(contentLength / inFlightRequestsBreaker.getOverhead()));
267267
// we will produce an error in the rest handler and one more when sending the error response
268268
RestRequest request = testRestRequest("/error", content, XContentType.JSON);
269269
ExceptionThrowingChannel channel = new ExceptionThrowingChannel(request, true);
@@ -276,7 +276,7 @@ public void testDispatchRequestAddsAndFreesBytesOnlyOnceOnError() {
276276

277277
public void testDispatchRequestLimitsBytes() {
278278
int contentLength = BREAKER_LIMIT.bytesAsInt() + 1;
279-
String content = randomAlphaOfLength(contentLength);
279+
String content = randomAlphaOfLength((int) Math.round(contentLength / inFlightRequestsBreaker.getOverhead()));
280280
RestRequest request = testRestRequest("/", content, XContentType.JSON);
281281
AssertingChannel channel = new AssertingChannel(request, true, RestStatus.SERVICE_UNAVAILABLE);
282282

@@ -287,7 +287,7 @@ public void testDispatchRequestLimitsBytes() {
287287
}
288288

289289
public void testDispatchRequiresContentTypeForRequestsWithContent() {
290-
String content = randomAlphaOfLengthBetween(1, BREAKER_LIMIT.bytesAsInt());
290+
String content = randomAlphaOfLength((int) Math.round(BREAKER_LIMIT.getBytes() / inFlightRequestsBreaker.getOverhead()));
291291
RestRequest request = testRestRequest("/", content, null);
292292
AssertingChannel channel = new AssertingChannel(request, true, RestStatus.NOT_ACCEPTABLE);
293293
restController = new RestController(
@@ -312,7 +312,7 @@ public void testDispatchDoesNotRequireContentTypeForRequestsWithoutContent() {
312312
}
313313

314314
public void testDispatchFailsWithPlainText() {
315-
String content = randomAlphaOfLengthBetween(1, BREAKER_LIMIT.bytesAsInt());
315+
String content = randomAlphaOfLength((int) Math.round(BREAKER_LIMIT.getBytes() / inFlightRequestsBreaker.getOverhead()));
316316
FakeRestRequest fakeRestRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY)
317317
.withContent(new BytesArray(content), null).withPath("/foo")
318318
.withHeaders(Collections.singletonMap("Content-Type", Collections.singletonList("text/plain"))).build();
@@ -342,7 +342,7 @@ public void testDispatchUnsupportedContentType() {
342342

343343
public void testDispatchWorksWithNewlineDelimitedJson() {
344344
final String mimeType = "application/x-ndjson";
345-
String content = randomAlphaOfLengthBetween(1, BREAKER_LIMIT.bytesAsInt());
345+
String content = randomAlphaOfLength((int) Math.round(BREAKER_LIMIT.getBytes() / inFlightRequestsBreaker.getOverhead()));
346346
FakeRestRequest fakeRestRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY)
347347
.withContent(new BytesArray(content), null).withPath("/foo")
348348
.withHeaders(Collections.singletonMap("Content-Type", Collections.singletonList(mimeType))).build();
@@ -366,7 +366,7 @@ public boolean supportsContentStream() {
366366

367367
public void testDispatchWithContentStream() {
368368
final String mimeType = randomFrom("application/json", "application/smile");
369-
String content = randomAlphaOfLengthBetween(1, BREAKER_LIMIT.bytesAsInt());
369+
String content = randomAlphaOfLength((int) Math.round(BREAKER_LIMIT.getBytes() / inFlightRequestsBreaker.getOverhead()));
370370
final List<String> contentTypeHeader = Collections.singletonList(mimeType);
371371
FakeRestRequest fakeRestRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY)
372372
.withContent(new BytesArray(content), RestRequest.parseContentType(contentTypeHeader)).withPath("/foo")

0 commit comments

Comments
 (0)