Skip to content

Commit 8b9a7ac

Browse files
erin2722MongoDB Bot
authored andcommitted
SERVER-106045 Redefine burstSize => burstCapacitySecs parameter (#37078)
GitOrigin-RevId: 6db9637e30a4f899a1ae3ab315df403f7c63fa69
1 parent 1858fbd commit 8b9a7ac

15 files changed

+100
-69
lines changed

jstests/noPassthrough/connection_establishment_rate_limiting_client_disconnect.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const testKillOnClientDisconnect = (conn) => {
5353
const testKillOnClientDisconnectOpts = {
5454
ingressConnectionEstablishmentRateLimiterEnabled: true,
5555
ingressConnectionEstablishmentRatePerSec: 1,
56-
ingressConnectionEstablishmentBurstSize: 1,
56+
ingressConnectionEstablishmentBurstCapacitySecs: 1,
5757
ingressConnectionEstablishmentMaxQueueDepth: maxQueueSize,
5858
};
5959
runTestStandaloneParamsSetAtStartup(testKillOnClientDisconnectOpts, testKillOnClientDisconnect);

jstests/noPassthrough/connection_establishment_rate_limiting_exemptions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const testExemptIPsFromRateLimit = (conn) => {
5050
const testExemptIPsFromRateLimitOpts = {
5151
ingressConnectionEstablishmentRateLimiterEnabled: true,
5252
ingressConnectionEstablishmentRatePerSec: 1,
53-
ingressConnectionEstablishmentBurstSize: 1,
53+
ingressConnectionEstablishmentBurstCapacitySecs: 1,
5454
ingressConnectionEstablishmentMaxQueueDepth: 0,
5555
ingressConnectionEstablishmentRateLimiterBypass: {ranges: [exemptIP]},
5656
};

jstests/noPassthrough/connection_establishment_rate_limiting_proxy_protocol.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ let rs = new ReplSetTest({
3434
setParameter: {
3535
ingressConnectionEstablishmentRateLimiterEnabled: true,
3636
ingressConnectionEstablishmentRatePerSec: 1,
37-
ingressConnectionEstablishmentBurstSize: 1,
37+
ingressConnectionEstablishmentBurstCapacitySecs: 1,
3838
ingressConnectionEstablishmentMaxQueueDepth: 0,
3939
ingressConnectionEstablishmentRateLimiterBypass: {ranges: [exemptIP]},
4040
featureFlagRateLimitIngressConnectionEstablishment: true

jstests/noPassthrough/connection_establishment_rate_limiting_stats.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ const testRateLimiterStats = (conn) => {
9595
const testRateLimiterStatsOpts = {
9696
ingressConnectionEstablishmentRateLimiterEnabled: true,
9797
ingressConnectionEstablishmentRatePerSec: 1,
98-
ingressConnectionEstablishmentBurstSize: 1,
98+
ingressConnectionEstablishmentBurstCapacitySecs: 1,
9999
ingressConnectionEstablishmentMaxQueueDepth: maxQueueSize,
100100
};
101101
runTestStandaloneParamsSetAtStartup(testRateLimiterStatsOpts, testRateLimiterStats);

jstests/noPassthrough/connection_establishment_server_params.js

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ function getIngressConnectionEstablishmentRatePerSec(mongo) {
55
.ingressConnectionEstablishmentRatePerSec;
66
}
77

8-
function getIngressConnectionEstablishmentBurstSize(mongo) {
9-
return mongo.adminCommand({getParameter: 1, ingressConnectionEstablishmentBurstSize: 1})
10-
.ingressConnectionEstablishmentBurstSize;
8+
function getingressConnectionEstablishmentBurstCapacitySecs(mongo) {
9+
return mongo.adminCommand({getParameter: 1, ingressConnectionEstablishmentBurstCapacitySecs: 1})
10+
.ingressConnectionEstablishmentBurstCapacitySecs;
1111
}
1212

1313
function getIngressConnectionEstablishmentMaxQueueDepthDefault(mongo) {
@@ -23,9 +23,14 @@ let ingressConnectionEstablishmentRatePerSecDefault =
2323
getIngressConnectionEstablishmentRatePerSec(mongo);
2424
assert.eq(ingressConnectionEstablishmentRatePerSecDefault, maxInt32);
2525

26-
let ingressConnectionEstablishmentBurstSizeDefault =
27-
getIngressConnectionEstablishmentBurstSize(mongo);
28-
assert.eq(ingressConnectionEstablishmentBurstSizeDefault, maxInt32);
26+
let ingressConnectionEstablishmentBurstCapacitySecsDefault =
27+
getingressConnectionEstablishmentBurstCapacitySecs(mongo);
28+
assert.eq(ingressConnectionEstablishmentBurstCapacitySecsDefault, Number.MAX_VALUE);
29+
30+
// There are infinite tokens available by default.
31+
let availableTokens =
32+
mongo.adminCommand({serverStatus: 1}).queues.ingressSessionEstablishment.totalAvailableTokens;
33+
assert.eq(availableTokens, Infinity);
2934

3035
let ingressConnectionEstablishmentMaxQueueDepthDefault =
3136
getIngressConnectionEstablishmentMaxQueueDepthDefault(mongo);
@@ -36,7 +41,7 @@ const runtimeSetValue = 10;
3641
assert.commandWorked(mongo.adminCommand({
3742
setParameter: 1,
3843
ingressConnectionEstablishmentRatePerSec: runtimeSetValue,
39-
ingressConnectionEstablishmentBurstSize: runtimeSetValue,
44+
ingressConnectionEstablishmentBurstCapacitySecs: runtimeSetValue,
4045
ingressConnectionEstablishmentMaxQueueDepth: runtimeSetValue
4146
}));
4247

@@ -45,9 +50,11 @@ assert.neq(ingressConnectionEstablishmentRatePerSec,
4550
ingressConnectionEstablishmentMaxQueueDepthDefault);
4651
assert.eq(ingressConnectionEstablishmentRatePerSec, runtimeSetValue);
4752

48-
let ingressConnectionEstablishmentBurstSize = getIngressConnectionEstablishmentBurstSize(mongo);
49-
assert.neq(ingressConnectionEstablishmentBurstSize, ingressConnectionEstablishmentBurstSizeDefault);
50-
assert.eq(ingressConnectionEstablishmentBurstSize, runtimeSetValue);
53+
let ingressConnectionEstablishmentBurstCapacitySecs =
54+
getingressConnectionEstablishmentBurstCapacitySecs(mongo);
55+
assert.neq(ingressConnectionEstablishmentBurstCapacitySecs,
56+
ingressConnectionEstablishmentBurstCapacitySecsDefault);
57+
assert.eq(ingressConnectionEstablishmentBurstCapacitySecs, runtimeSetValue);
5158

5259
let ingressConnectionEstablishmentMaxQueueDepth =
5360
mongo.adminCommand({getParameter: 1, ingressConnectionEstablishmentMaxQueueDepth: 1})
@@ -61,16 +68,17 @@ const startupSetValue = 50;
6168
mongo = MongoRunner.runMongod({
6269
setParameter: {
6370
ingressConnectionEstablishmentRatePerSec: startupSetValue,
64-
ingressConnectionEstablishmentBurstSize: startupSetValue,
71+
ingressConnectionEstablishmentBurstCapacitySecs: startupSetValue,
6572
ingressConnectionEstablishmentMaxQueueDepth: startupSetValue
6673
}
6774
});
6875

6976
ingressConnectionEstablishmentRatePerSec = getIngressConnectionEstablishmentRatePerSec(mongo);
7077
assert.eq(ingressConnectionEstablishmentRatePerSec, startupSetValue);
7178

72-
ingressConnectionEstablishmentBurstSize = getIngressConnectionEstablishmentBurstSize(mongo);
73-
assert.eq(ingressConnectionEstablishmentBurstSize, startupSetValue);
79+
ingressConnectionEstablishmentBurstCapacitySecs =
80+
getingressConnectionEstablishmentBurstCapacitySecs(mongo);
81+
assert.eq(ingressConnectionEstablishmentBurstCapacitySecs, startupSetValue);
7482

7583
ingressConnectionEstablishmentMaxQueueDepth =
7684
mongo.adminCommand({getParameter: 1, ingressConnectionEstablishmentMaxQueueDepth: 1})
@@ -89,9 +97,10 @@ assert.eq(ingressConnectionEstablishmentRatePerSec, stringSetValue);
8997
MongoRunner.stopMongod(mongo);
9098

9199
mongo = MongoRunner.runMongod(
92-
{setParameter: 'ingressConnectionEstablishmentBurstSize=' + stringSetValue});
93-
ingressConnectionEstablishmentBurstSize = getIngressConnectionEstablishmentBurstSize(mongo);
94-
assert.eq(ingressConnectionEstablishmentBurstSize, stringSetValue);
100+
{setParameter: 'ingressConnectionEstablishmentBurstCapacitySecs=' + stringSetValue});
101+
ingressConnectionEstablishmentBurstCapacitySecs =
102+
getingressConnectionEstablishmentBurstCapacitySecs(mongo);
103+
assert.eq(ingressConnectionEstablishmentBurstCapacitySecs, stringSetValue);
95104
MongoRunner.stopMongod(mongo);
96105

97106
mongo = MongoRunner.runMongod(
@@ -101,3 +110,32 @@ ingressConnectionEstablishmentMaxQueueDepth =
101110
.ingressConnectionEstablishmentMaxQueueDepth;
102111
assert.eq(ingressConnectionEstablishmentMaxQueueDepth, stringSetValue);
103112
MongoRunner.stopMongod(mongo);
113+
114+
// Make sure that increasing the burstSize results in increasing the available tokens in the bucket
115+
const marginOfError = 5; // +/- 5 tokens just in case there is rounding errors/clock skew
116+
const refreshRate = 10000;
117+
const initialBurstCapacitySecs = 0.5;
118+
mongo = MongoRunner.runMongod({
119+
setParameter: {
120+
ingressConnectionEstablishmentRatePerSec: refreshRate,
121+
ingressConnectionEstablishmentBurstCapacitySecs: initialBurstCapacitySecs,
122+
}
123+
});
124+
let initialTokens =
125+
mongo.adminCommand({serverStatus: 1}).queues.ingressSessionEstablishment.totalAvailableTokens;
126+
const targetTokens = refreshRate * initialBurstCapacitySecs;
127+
assert.between(targetTokens - marginOfError, initialTokens, targetTokens + marginOfError);
128+
129+
const newBurstCapacitySecs = 2;
130+
const newTargetTokens = refreshRate * newBurstCapacitySecs;
131+
assert.commandWorked(mongo.adminCommand(
132+
{setParameter: 1, ingressConnectionEstablishmentBurstCapacitySecs: newBurstCapacitySecs}));
133+
assert.soon(() => {
134+
const newTokens = mongo.adminCommand({serverStatus: 1})
135+
.queues.ingressSessionEstablishment.totalAvailableTokens;
136+
jsTestLog("New tokens: " + newTokens);
137+
return newTargetTokens - marginOfError <= newTokens &&
138+
newTokens <= newTargetTokens + marginOfError;
139+
});
140+
141+
MongoRunner.stopMongod(mongo);

jstests/noPassthrough/libs/conn_establishment_rate_limiter_helpers.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const runTestStandaloneParamsSetAtStartup = (setParams, testCase) => {
3232
mongod.adminCommand({
3333
setParameter: 1,
3434
ingressConnectionEstablishmentRatePerSec: 10.0,
35-
ingressConnectionEstablishmentBurstSize: 500.0,
35+
ingressConnectionEstablishmentBurstCapacitySecs: 500.0,
3636
});
3737

3838
MongoRunner.stopMongod(mongod);
@@ -57,7 +57,7 @@ export const runTestStandaloneParamsSetAtRuntime = (setParams, testCase) => {
5757
mongod.adminCommand({
5858
setParameter: 1,
5959
ingressConnectionEstablishmentRatePerSec: 10.0,
60-
ingressConnectionEstablishmentBurstSize: 500.0,
60+
ingressConnectionEstablishmentBurstCapacitySecs: 500.0,
6161
});
6262

6363
MongoRunner.stopMongod(mongod);
@@ -83,7 +83,7 @@ export const runTestReplSet = (setParams, testCase) => {
8383
replSet.getPrimary().adminCommand({
8484
setParameter: 1,
8585
ingressConnectionEstablishmentRatePerSec: 10.0,
86-
ingressConnectionEstablishmentBurstSize: 500.0,
86+
ingressConnectionEstablishmentBurstCapacitySecs: 500.0,
8787
});
8888

8989
replSet.stopSet();
@@ -118,7 +118,7 @@ export const runTestShardedCluster = (setParams, testCase) => {
118118
st.s0.adminCommand({
119119
setParameter: 1,
120120
ingressConnectionEstablishmentRatePerSec: 1000.0,
121-
ingressConnectionEstablishmentBurstSize: 500.0,
121+
ingressConnectionEstablishmentBurstCapacitySecs: 500.0,
122122
ingressConnectionEstablishmentMaxQueueDepth: 100,
123123
});
124124

src/mongo/db/admission/rate_limiter.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,20 +164,14 @@ void RateLimiter::recordExemption() {
164164
_impl->stats.exemptedAdmissions.incrementRelaxed();
165165
}
166166

167-
void RateLimiter::setRefreshRatePerSec(double refreshRatePerSec) {
168-
auto lk = _impl->rwMutex.writeLock();
169-
_impl->tokenBucket.reset(refreshRatePerSec, _impl->tokenBucket.burst());
170-
}
171-
172-
void RateLimiter::setBurstSize(double burstSize) {
167+
void RateLimiter::updateRateParameters(double refreshRatePerSec, double burstSize) {
173168
uassert(ErrorCodes::InvalidOptions,
174169
fmt::format("burstSize cannot be less than 1.0. burstSize={}; rateLimiterName={}",
175170
burstSize,
176171
_impl->name),
177172
burstSize >= 1.0);
178-
179173
auto lk = _impl->rwMutex.writeLock();
180-
_impl->tokenBucket.reset(_impl->tokenBucket.rate(), burstSize);
174+
_impl->tokenBucket.reset(refreshRatePerSec, burstSize);
181175
}
182176

183177
void RateLimiter::setMaxQueueDepth(int64_t maxQueueDepth) {

src/mongo/db/admission/rate_limiter.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,12 @@ class RateLimiter {
107107
void recordExemption();
108108

109109
/**
110-
* The number of tokens issued per second when rate-limiting has kicked in. Tokens will be
111-
* issued smoothly, rather than all at once every 1 second.
110+
* refreshRate is the number of tokens issued per second when rate-limiting has kicked in.
111+
* Tokens will be issued smoothly, rather than all at once every 1 second. The burstSize is the
112+
* maximum number of tokens that will be issued before rate-limiting kicks in (ie, the maximum
113+
* number of tokens that can accumulate in the bucket).
112114
*/
113-
void setRefreshRatePerSec(double refreshRatePerSec);
114-
115-
/**
116-
* The maximum number of tokens that will be issued before rate-limiting kicks in (ie, the
117-
* maximum number of tokens that can accumulate in the bucket).
118-
*/
119-
void setBurstSize(double burstSize);
115+
void updateRateParameters(double refreshRatePerSec, double burstSize);
120116

121117
/**
122118
* The maximum number of requests enqueued waiting for a token. Token requests that come in and

src/mongo/db/admission/rate_limiter_util_test.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ TEST_F(RateLimiterTest, BasicTokenAcquisition) {
9797
TEST_F(RateLimiterTest, InvalidBurstSize) {
9898
ASSERT_THROWS_CODE(RateLimiter(1.0, 0, 0), DBException, ErrorCodes::InvalidOptions);
9999

100-
RateLimiter rateLimiter(DBL_MAX, DBL_MAX, INT_MAX);
101-
ASSERT_THROWS_CODE(rateLimiter.setBurstSize(0), DBException, ErrorCodes::InvalidOptions);
100+
RateLimiter rateLimiter(DBL_MAX, DBL_MAX, INT_MAX, "InvalidBurstSize");
101+
ASSERT_THROWS_CODE(
102+
rateLimiter.updateRateParameters(1.0, 0), DBException, ErrorCodes::InvalidOptions);
102103
}
103104

104105
// Verify that a newly initialized RateLimiter can immediately dispense up to its burst rate of

src/mongo/transport/session_establishment_rate_limiter.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ namespace transport {
3939

4040
SessionEstablishmentRateLimiter::SessionEstablishmentRateLimiter()
4141
: _rateLimiter(gIngressConnectionEstablishmentRatePerSec.load(),
42-
gIngressConnectionEstablishmentBurstSize.load(),
42+
gIngressConnectionEstablishmentRatePerSec.load() *
43+
gIngressConnectionEstablishmentBurstCapacitySecs.load(),
4344
gIngressConnectionEstablishmentMaxQueueDepth.load(),
4445
"SessionEstablishmentRateLimiter") {}
4546

@@ -63,7 +64,6 @@ SessionEstablishmentRateLimiter* SessionEstablishmentRateLimiter::get(ServiceCon
6364
return rateLimiter;
6465
}
6566

66-
6767
Status SessionEstablishmentRateLimiter::throttleIfNeeded(Client* client) {
6868
// Check if the session is exempt from rate limiting based on its IP.
6969
serverGlobalParams.maxEstablishingConnsOverride.refreshSnapshot(_maxEstablishingConnsOverride);
@@ -89,7 +89,6 @@ Status SessionEstablishmentRateLimiter::throttleIfNeeded(Client* client) {
8989
return s;
9090
}
9191

92-
9392
void SessionEstablishmentRateLimiter::appendStatsConnections(BSONObjBuilder* bob) const {
9493
bob->append("queuedForEstablishment", queued());
9594

0 commit comments

Comments
 (0)