diff options
author | Cheahuychou Mao <cheahuychou.mao@mongodb.com> | 2020-02-04 12:17:57 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-05 19:54:49 +0000 |
commit | c2e39888d052972e897b4dc8c170201e8467f964 (patch) | |
tree | 3729d9922ee55a06e7f3b47b0b4f01e1146fc8ae | |
parent | ad06b5ffbc39838e92cae0b73f51d3cf5a417116 (diff) | |
download | mongo-c2e39888d052972e897b4dc8c170201e8467f964.tar.gz |
SERVER-45947 Make hedging server parameters settable at runtime
-rw-r--r-- | jstests/sharding/hedged_reads_server_parameters.js | 40 | ||||
-rw-r--r-- | src/mongo/s/hedge_options_util.cpp | 9 | ||||
-rw-r--r-- | src/mongo/s/hedge_options_util_test.cpp | 7 | ||||
-rw-r--r-- | src/mongo/s/mongos_server_parameters.cpp | 32 | ||||
-rw-r--r-- | src/mongo/s/mongos_server_parameters.h | 11 | ||||
-rw-r--r-- | src/mongo/s/mongos_server_parameters.idl | 28 |
6 files changed, 77 insertions, 50 deletions
diff --git a/jstests/sharding/hedged_reads_server_parameters.js b/jstests/sharding/hedged_reads_server_parameters.js index dab38ab6013..7cfa9d70c5a 100644 --- a/jstests/sharding/hedged_reads_server_parameters.js +++ b/jstests/sharding/hedged_reads_server_parameters.js @@ -8,10 +8,7 @@ */ (function() { -const st = new ShardingTest({ - shards: 2, - mongosOptions: {setParameter: {maxTimeMSThresholdForHedging: 1500, hedgingDelayPercentage: 50}} -}); +const st = new ShardingTest({shards: 2}); const dbName = "foo"; const collName = "bar"; const ns = dbName + "." + collName; @@ -21,29 +18,42 @@ assert.commandWorked(st.s.adminCommand({enableSharding: dbName})); st.ensurePrimaryShard(dbName, st.shard0.shardName); assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1}})); -// With maxTimeMS. +assert.commandWorked(st.s.adminCommand( + {setParameter: 1, maxTimeMSThresholdForHedging: 1500, hedgingDelayPercentage: 50})); + +// With maxTimeMS < maxTimeMSThresholdForHedging, expect hedging. assert.commandWorked(st.s.getDB(dbName).runCommand( {query: {find: collName, maxTimeMS: 1000}, $readPreference: {mode: "nearest", hedge: {}}})); -// Without maxTimeMS. -st.restartMongos(0, { - restart: true, - setParameter: {defaultHedgingDelayMS: 800}, -}); +// With maxTimeMS > maxTimeMSThresholdForHedging, expect no hedging. +assert.commandWorked(st.s.getDB(dbName).runCommand( + {query: {find: collName, maxTimeMS: 1600}, $readPreference: {mode: "nearest", hedge: {}}})); + +// Without maxTimeMS, expect hedging. +assert.commandWorked(st.s.adminCommand({setParameter: 1, defaultHedgingDelayMS: 800})); assert.commandWorked(st.s.getDB(dbName).runCommand( {query: {count: collName}, $readPreference: {mode: "secondaryPreferred", hedge: {}}})); -// readHedgingMode "off". -st.restartMongos(0, { - restart: true, - setParameter: {readHedgingMode: "off"}, -}); +// readHedgingMode "off", expect no hedging. +st.s.adminCommand({setParameter: 1, readHedgingMode: "off"}); assert.commandWorked(st.s.getDB(dbName).runCommand({ query: {distinct: collName, key: "x"}, $readPreference: {mode: "primaryPreferred", hedge: {}} })); +// Test server parameter validation. +assert.commandFailedWithCode(st.s.adminCommand({setParameter: 1, maxTimeMSThresholdForHedging: -1}), + ErrorCodes.BadValue); +assert.commandFailedWithCode(st.s.adminCommand({setParameter: 1, hedgingDelayPercentage: -1}), + ErrorCodes.BadValue); +assert.commandFailedWithCode(st.s.adminCommand({setParameter: 1, hedgingDelayPercentage: 101}), + ErrorCodes.BadValue); +assert.commandFailedWithCode(st.s.adminCommand({setParameter: 1, defaultHedgingDelayMS: -1}), + ErrorCodes.BadValue); +assert.commandFailedWithCode(st.s.adminCommand({setParameter: 1, readHedgingMode: "invalidMode"}), + ErrorCodes.BadValue); + st.stop(); })(); diff --git a/src/mongo/s/hedge_options_util.cpp b/src/mongo/s/hedge_options_util.cpp index 9301a416bcf..d4ffd133f65 100644 --- a/src/mongo/s/hedge_options_util.cpp +++ b/src/mongo/s/hedge_options_util.cpp @@ -39,14 +39,15 @@ boost::optional<executor::RemoteCommandRequestOnAny::HedgeOptions> extractHedgeO OperationContext* opCtx, const BSONObj& cmdObj) { const auto hedgingMode = ReadPreferenceSetting::get(opCtx).hedgingMode; - if (gReadHedgingMode == kReadHedgingModeOn && hedgingMode && hedgingMode->getEnabled()) { + if (gReadHedgingMode.load() == ReadHedgingMode::kOn && hedgingMode && + hedgingMode->getEnabled()) { boost::optional<int> maxTimeMS; if (auto cmdOptionMaxTimeMSField = cmdObj[QueryRequest::cmdOptionMaxTimeMS]) { maxTimeMS = uassertStatusOK(QueryRequest::parseMaxTimeMS(cmdOptionMaxTimeMSField)); } // Check if the operation is worth hedging. - if (maxTimeMS && maxTimeMS > gMaxTimeMSThresholdForHedging) { + if (maxTimeMS && maxTimeMS > gMaxTimeMSThresholdForHedging.load()) { return boost::none; } @@ -55,8 +56,8 @@ boost::optional<executor::RemoteCommandRequestOnAny::HedgeOptions> extractHedgeO bool shouldDelayHedging = hedgingMode->getDelay(); if (shouldDelayHedging) { - delay = maxTimeMS ? Milliseconds{gHedgingDelayPercentage * maxTimeMS.get() / 100} - : Milliseconds{gDefaultHedgingDelayMS}; + delay = maxTimeMS ? Milliseconds{gHedgingDelayPercentage.load() * maxTimeMS.get() / 100} + : Milliseconds{gDefaultHedgingDelayMS.load()}; } return executor::RemoteCommandRequestOnAny::HedgeOptions{1, delay}; diff --git a/src/mongo/s/hedge_options_util_test.cpp b/src/mongo/s/hedge_options_util_test.cpp index 1fd54e39082..1407caa6e01 100644 --- a/src/mongo/s/hedge_options_util_test.cpp +++ b/src/mongo/s/hedge_options_util_test.cpp @@ -112,9 +112,10 @@ protected: static inline const BSONObj kDefaultParameters = BSON(kReadHedgingModeFieldName - << "on" << kMaxTimeMSThresholdForHedgingFieldName << gMaxTimeMSThresholdForHedging - << kHedgingDelayPercentageFieldName << gHedgingDelayPercentage - << kDefaultHedgingDelayMSFieldName << gDefaultHedgingDelayMS); + << "on" << kMaxTimeMSThresholdForHedgingFieldName + << gMaxTimeMSThresholdForHedging.load() << kHedgingDelayPercentageFieldName + << gHedgingDelayPercentage.load() << kDefaultHedgingDelayMSFieldName + << gDefaultHedgingDelayMS.load()); private: ServiceContext::UniqueServiceContext _serviceCtx = ServiceContext::make(); diff --git a/src/mongo/s/mongos_server_parameters.cpp b/src/mongo/s/mongos_server_parameters.cpp index de9d5507598..8adb722635b 100644 --- a/src/mongo/s/mongos_server_parameters.cpp +++ b/src/mongo/s/mongos_server_parameters.cpp @@ -29,18 +29,34 @@ #include "mongo/s/mongos_server_parameters.h" +#include "mongo/base/status.h" +#include "mongo/s/mongos_server_parameters_gen.h" #include "mongo/util/str.h" namespace mongo { -/** - * Validation callback for setParameter 'readHedgingMode'. - */ -Status validateReadHedgingMode(const std::string& mode) { - if (mode != kReadHedgingModeOn && mode != kReadHedgingModeOff) { - return {ErrorCodes::BadValue, - str::stream() << "readHedgingMode must be either \"" << kReadHedgingModeOn - << "\" or \"" << kReadHedgingModeOff << "\""}; +namespace { +std::string toReadHedgingModeString(ReadHedgingMode readHedgingMode) { + return readHedgingMode == ReadHedgingMode::kOn ? "on" : "off"; +} +} // namespace + +AtomicWord<ReadHedgingMode> gReadHedgingMode{ReadHedgingMode::kOn}; + +void HedgingModeServerParameter::append(OperationContext*, + BSONObjBuilder& builder, + const std::string& name) { + builder.append(name, toReadHedgingModeString(gReadHedgingMode.load())); +} + +Status HedgingModeServerParameter::setFromString(const std::string& modeStr) { + if (modeStr == "on") { + gReadHedgingMode.store(ReadHedgingMode::kOn); + } else if (modeStr == "off") { + gReadHedgingMode.store(ReadHedgingMode::kOff); + } else { + return Status{ErrorCodes::BadValue, + str::stream() << "Unrecognized readHedgingMode '" << modeStr << "'"}; } return Status::OK(); } diff --git a/src/mongo/s/mongos_server_parameters.h b/src/mongo/s/mongos_server_parameters.h index 9c2a580278b..b992e3f214c 100644 --- a/src/mongo/s/mongos_server_parameters.h +++ b/src/mongo/s/mongos_server_parameters.h @@ -29,18 +29,13 @@ #pragma once +#include "mongo/platform/atomic_word.h" #include "mongo/platform/basic.h" -#include "mongo/base/status.h" - namespace mongo { -constexpr auto kReadHedgingModeOn = "on"; -constexpr auto kReadHedgingModeOff = "off"; +enum ReadHedgingMode { kOn, kOff }; -/** - * Validation callback for setParameter 'readHedgingMode'. - */ -Status validateReadHedgingMode(const std::string& mode); +extern AtomicWord<ReadHedgingMode> gReadHedgingMode; } // namespace mongo diff --git a/src/mongo/s/mongos_server_parameters.idl b/src/mongo/s/mongos_server_parameters.idl index aaac5f4d2dc..00376d40cf3 100644 --- a/src/mongo/s/mongos_server_parameters.idl +++ b/src/mongo/s/mongos_server_parameters.idl @@ -63,35 +63,39 @@ server_parameters: readHedgingMode: description: >- Enables hedged reads. - set_at: [ startup ] - cpp_vartype: std::string - cpp_varname: "gReadHedgingMode" - default: "on" - validator: - callback: "validateReadHedgingMode" + set_at: [ startup, runtime ] + cpp_class: + name: HedgingModeServerParameter maxTimeMSThresholdForHedging: description: >- The upper threshold for the expected running time of an operation (maxTimeMS) for it to be worth hedging. - set_at: [ startup ] - cpp_vartype: int + set_at: [ startup, runtime ] + cpp_vartype: AtomicWord<int> cpp_varname: "gMaxTimeMSThresholdForHedging" + validator: + gte: 0 default: 5000 hedgingDelayPercentage: description: >- The percentage of maxTimeMS to wait for before dispatching subsequent reads. - set_at: [ startup ] - cpp_vartype: int + set_at: [ startup, runtime ] + cpp_vartype: AtomicWord<int> cpp_varname: "gHedgingDelayPercentage" + validator: + gte: 0 + lte: 100 default: 25 defaultHedgingDelayMS: description: >- The default wait time in milliseconds before dispatching subsequent reads if maxTimeMS is not given. - set_at: [ startup ] - cpp_vartype: int + set_at: [ startup, runtime ] + cpp_vartype: AtomicWord<int> cpp_varname: "gDefaultHedgingDelayMS" + validator: + gte: 0 default: 1250 |