mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-27 02:18:42 +00:00
Add getAsRatio
to Settings class, allow DiskThresholdDecider to take percentages
Adds new RatioValue class that parses ratios between 0-100% expressed in either floating-point (0.13) or percentage (51.12%) notation. Closes #5690
This commit is contained in:
parent
3248359660
commit
211f740100
@ -37,7 +37,7 @@ curl -XPUT localhost:9200/test/_settings -d '{
|
||||
}'
|
||||
--------------------------------------------------
|
||||
|
||||
`index.routing.allocation.require.*` can be used to
|
||||
`index.routing.allocation.require.*` can be used to
|
||||
specify a number of rules, all of which MUST match in order for a shard
|
||||
to be allocated to a node. This is in contrast to `include` which will
|
||||
include a node if ANY rule matches.
|
||||
@ -117,14 +117,14 @@ Once enabled, Elasticsearch uses two watermarks to decide whether
|
||||
shards should be allocated or can remain on the node.
|
||||
|
||||
`cluster.routing.allocation.disk.watermark.low` controls the low
|
||||
watermark for disk usage. It defaults to 0.70, meaning ES will not
|
||||
watermark for disk usage. It defaults to 70%, meaning ES will not
|
||||
allocate new shards to nodes once they have more than 70% disk
|
||||
used. It can also be set to an absolute byte value (like 500mb) to
|
||||
prevent ES from allocating shards if less than the configured amount
|
||||
of space is available.
|
||||
|
||||
`cluster.routing.allocation.disk.watermark.high` controls the high
|
||||
watermark. It defaults to 0.85, meaning ES will attempt to relocate
|
||||
watermark. It defaults to 85%, meaning ES will attempt to relocate
|
||||
shards to another node if the node disk usage rises above 85%. It can
|
||||
also be set to an absolute byte value (similar to the low watermark)
|
||||
to relocate shards once less than the configured amount of space is
|
||||
|
@ -28,6 +28,7 @@ import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.unit.RatioValue;
|
||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
||||
|
||||
import java.util.Map;
|
||||
@ -109,8 +110,8 @@ public class DiskThresholdDecider extends AllocationDecider {
|
||||
@Inject
|
||||
public DiskThresholdDecider(Settings settings, NodeSettingsService nodeSettingsService) {
|
||||
super(settings);
|
||||
String lowWatermark = settings.get(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK, "0.7");
|
||||
String highWatermark = settings.get(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK, "0.85");
|
||||
String lowWatermark = settings.get(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK, "70%");
|
||||
String highWatermark = settings.get(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK, "85%");
|
||||
|
||||
if (!validWatermarkSetting(lowWatermark)) {
|
||||
throw new ElasticsearchParseException("Unable to parse low watermark: [" + lowWatermark + "]");
|
||||
@ -307,8 +308,8 @@ public class DiskThresholdDecider extends AllocationDecider {
|
||||
*/
|
||||
public double thresholdPercentageFromWatermark(String watermark) {
|
||||
try {
|
||||
return 100.0 * Double.parseDouble(watermark);
|
||||
} catch (NumberFormatException ex) {
|
||||
return RatioValue.parseRatioValue(watermark).getAsPercent();
|
||||
} catch (ElasticsearchParseException ex) {
|
||||
return 100.0;
|
||||
}
|
||||
}
|
||||
@ -331,12 +332,9 @@ public class DiskThresholdDecider extends AllocationDecider {
|
||||
*/
|
||||
public boolean validWatermarkSetting(String watermark) {
|
||||
try {
|
||||
double w = Double.parseDouble(watermark);
|
||||
if (w < 0 || w > 1.0) {
|
||||
return false;
|
||||
}
|
||||
RatioValue.parseRatioValue(watermark);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
} catch (ElasticsearchParseException e) {
|
||||
try {
|
||||
ByteSizeValue.parseBytesSizeValue(watermark);
|
||||
return true;
|
||||
|
@ -388,6 +388,16 @@ public class ImmutableSettings implements Settings {
|
||||
return MemorySizeValue.parseBytesSizeValueOrHeapRatio(get(settings, defaultValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RatioValue getAsRatio(String setting, String defaultValue) throws SettingsException {
|
||||
return RatioValue.parseRatioValue(get(setting, defaultValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RatioValue getAsRatio(String[] settings, String defaultValue) throws SettingsException {
|
||||
return RatioValue.parseRatioValue(get(settings, defaultValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SizeValue getAsSize(String setting, SizeValue defaultValue) throws SettingsException {
|
||||
return parseSizeValue(get(setting), defaultValue);
|
||||
|
@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.unit.RatioValue;
|
||||
import org.elasticsearch.common.unit.SizeValue;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
@ -212,6 +213,20 @@ public interface Settings extends ToXContent {
|
||||
*/
|
||||
ByteSizeValue getAsMemory(String[] setting, String defaultValue) throws SettingsException;
|
||||
|
||||
/**
|
||||
* Returns the setting value (as a RatioValue) associated with the setting key. Provided values can
|
||||
* either be a percentage value (eg. 23%), or expressed as a floating point number (eg. 0.23). If
|
||||
* it does not exist, parses the default value provided.
|
||||
*/
|
||||
RatioValue getAsRatio(String setting, String defaultValue) throws SettingsException;
|
||||
|
||||
/**
|
||||
* Returns the setting value (as a RatioValue) associated with the setting key. Provided values can
|
||||
* either be a percentage value (eg. 23%), or expressed as a floating point number (eg. 0.23). If
|
||||
* it does not exist, parses the default value provided.
|
||||
*/
|
||||
RatioValue getAsRatio(String[] settings, String defaultValue) throws SettingsException;
|
||||
|
||||
/**
|
||||
* Returns the setting value (as size) associated with the setting key. If it does not exists,
|
||||
* returns the default value provided.
|
||||
|
76
src/main/java/org/elasticsearch/common/unit/RatioValue.java
Normal file
76
src/main/java/org/elasticsearch/common/unit/RatioValue.java
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.common.unit;
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
|
||||
/**
|
||||
* Utility class to represent ratio and percentage values between 0 and 100
|
||||
*/
|
||||
public class RatioValue {
|
||||
private final double percent;
|
||||
|
||||
public RatioValue(double percent) {
|
||||
this.percent = percent;
|
||||
}
|
||||
|
||||
public double getAsRatio() {
|
||||
return this.percent / 100.0;
|
||||
}
|
||||
|
||||
public double getAsPercent() {
|
||||
return this.percent;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.percent + "%";
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the provided string as a {@link RatioValue}, the string can
|
||||
* either be in percentage format (eg. 73.5%), or a floating-point ratio
|
||||
* format (eg. 0.735)
|
||||
*/
|
||||
public static RatioValue parseRatioValue(String sValue) {
|
||||
if (sValue.endsWith("%")) {
|
||||
final String percentAsString = sValue.substring(0, sValue.length() - 1);
|
||||
try {
|
||||
final double percent = Double.parseDouble(percentAsString);
|
||||
if (percent < 0 || percent > 100) {
|
||||
throw new ElasticsearchParseException("Percentage should be in [0-100], got " + percentAsString);
|
||||
}
|
||||
return new RatioValue(Math.abs(percent));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ElasticsearchParseException("Failed to parse [" + percentAsString + "] as a double", e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
double ratio = Double.parseDouble(sValue);
|
||||
if (ratio < 0 || ratio > 1.0) {
|
||||
throw new ElasticsearchParseException("Ratio should be in [0-1.0], got " + ratio);
|
||||
}
|
||||
return new RatioValue(100.0 * Math.abs(ratio));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ElasticsearchParseException("Invalid ratio or percentage: [" + sValue + "]");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -155,7 +155,7 @@ public class DiskThresholdDeciderTests extends ElasticsearchAllocationTestCase {
|
||||
// node2 now should not have new shards allocated to it, but shards can remain
|
||||
diskSettings = settingsBuilder()
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED, true)
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK, 0.6)
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK, "60%")
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK, 0.7).build();
|
||||
|
||||
deciders = new AllocationDeciders(ImmutableSettings.EMPTY,
|
||||
@ -430,7 +430,7 @@ public class DiskThresholdDeciderTests extends ElasticsearchAllocationTestCase {
|
||||
Settings diskSettings = settingsBuilder()
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED, true)
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK, 0.7)
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK, 0.71).build();
|
||||
.put(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK, "71%").build();
|
||||
|
||||
Map<String, DiskUsage> usages = new HashMap<>();
|
||||
usages.put("node1", new DiskUsage("node1", 100, 31)); // 69% used
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.common.unit;
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
* Tests for the {@link RatioValue} class
|
||||
*/
|
||||
public class RatioValueTests extends ElasticsearchTestCase {
|
||||
|
||||
@Test
|
||||
public void testParsing() {
|
||||
assertThat(RatioValue.parseRatioValue("100%").toString(), is("100.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("0%").toString(), is("0.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("-0%").toString(), is("0.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("15.1%").toString(), is("15.1%"));
|
||||
assertThat(RatioValue.parseRatioValue("0.1%").toString(), is("0.1%"));
|
||||
assertThat(RatioValue.parseRatioValue("1.0").toString(), is("100.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("0").toString(), is("0.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("-0").toString(), is("0.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("0.0").toString(), is("0.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("-0.0").toString(), is("0.0%"));
|
||||
assertThat(RatioValue.parseRatioValue("0.151").toString(), is("15.1%"));
|
||||
assertThat(RatioValue.parseRatioValue("0.001").toString(), is("0.1%"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeCase() {
|
||||
testInvalidRatio("100.0001%");
|
||||
testInvalidRatio("-0.1%");
|
||||
testInvalidRatio("1a0%");
|
||||
testInvalidRatio("2");
|
||||
testInvalidRatio("-0.01");
|
||||
testInvalidRatio("0.1.0");
|
||||
testInvalidRatio("five");
|
||||
testInvalidRatio("1/2");
|
||||
}
|
||||
|
||||
public void testInvalidRatio(String r) {
|
||||
try {
|
||||
RatioValue.parseRatioValue(r);
|
||||
fail("Value: [" + r + "] should be an invalid ratio");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user