Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2d4451f

Browse files
committed
Rate Limiting PoC
Some caveats: - This doesn't abide yet to the agreed API as declared in linkerd/linkerd2-proxy-api#388 . Instead, this is based on an earlier API proposal using "specifiers" to define the buckets keys. - The limiting logic has been added directly into the inbound http policy middleware. It relies on [governor](https://docs.rs/governor/latest/governor/). If we're not allowing to configure bursting in the first implementation, we might reconsider implementing something simpler directly ourselves. - There is actually an additional middleware (`RateLimitPolicyService`) that is currently commented out (used in the initial demo), that implemented a simpler approach, inspired by Tower's own rate-limiting middleware.
1 parent ef779d0 commit 2d4451f

File tree

12 files changed

+594
-10
lines changed

12 files changed

+594
-10
lines changed

Cargo.lock

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,12 @@ dependencies = [
379379
"cfg-if",
380380
]
381381

382+
[[package]]
383+
name = "crossbeam-utils"
384+
version = "0.8.20"
385+
source = "registry+https://github.com/rust-lang/crates.io-index"
386+
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
387+
382388
[[package]]
383389
name = "crypto-common"
384390
version = "0.1.6"
@@ -389,6 +395,19 @@ dependencies = [
389395
"typenum",
390396
]
391397

398+
[[package]]
399+
name = "dashmap"
400+
version = "5.5.3"
401+
source = "registry+https://github.com/rust-lang/crates.io-index"
402+
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
403+
dependencies = [
404+
"cfg-if",
405+
"hashbrown 0.14.3",
406+
"lock_api",
407+
"once_cell",
408+
"parking_lot_core",
409+
]
410+
392411
[[package]]
393412
name = "data-encoding"
394413
version = "2.6.0"
@@ -670,6 +689,17 @@ dependencies = [
670689
"syn",
671690
]
672691

692+
[[package]]
693+
name = "futures-macro"
694+
version = "0.3.30"
695+
source = "registry+https://github.com/rust-lang/crates.io-index"
696+
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
697+
dependencies = [
698+
"proc-macro2",
699+
"quote",
700+
"syn",
701+
]
702+
673703
[[package]]
674704
name = "futures-sink"
675705
version = "0.3.31"
@@ -682,6 +712,12 @@ version = "0.3.31"
682712
source = "registry+https://github.com/rust-lang/crates.io-index"
683713
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
684714

715+
[[package]]
716+
name = "futures-timer"
717+
version = "3.0.3"
718+
source = "registry+https://github.com/rust-lang/crates.io-index"
719+
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
720+
685721
[[package]]
686722
name = "futures-util"
687723
version = "0.3.31"
@@ -733,6 +769,26 @@ version = "0.3.1"
733769
source = "registry+https://github.com/rust-lang/crates.io-index"
734770
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
735771

772+
[[package]]
773+
name = "governor"
774+
version = "0.6.3"
775+
source = "registry+https://github.com/rust-lang/crates.io-index"
776+
checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b"
777+
dependencies = [
778+
"cfg-if",
779+
"dashmap",
780+
"futures",
781+
"futures-timer",
782+
"no-std-compat",
783+
"nonzero_ext",
784+
"parking_lot",
785+
"portable-atomic",
786+
"quanta",
787+
"rand",
788+
"smallvec",
789+
"spinning_top",
790+
]
791+
736792
[[package]]
737793
name = "gzip-header"
738794
version = "1.0.0"
@@ -1255,13 +1311,17 @@ dependencies = [
12551311
"arbitrary",
12561312
"bytes",
12571313
"futures",
1314+
"governor",
12581315
"http",
12591316
"hyper",
12601317
"libfuzzer-sys",
12611318
"linkerd-app-core",
12621319
"linkerd-app-test",
1320+
"linkerd-dns-name",
1321+
"linkerd-error",
12631322
"linkerd-http-access-log",
12641323
"linkerd-http-metrics",
1324+
"linkerd-identity",
12651325
"linkerd-idle-cache",
12661326
"linkerd-io",
12671327
"linkerd-meshtls",
@@ -2385,8 +2445,6 @@ dependencies = [
23852445
[[package]]
23862446
name = "linkerd2-proxy-api"
23872447
version = "0.14.0"
2388-
source = "registry+https://github.com/rust-lang/crates.io-index"
2389-
checksum = "26c72fb98d969e1e94e95d52a6fcdf4693764702c369e577934256e72fb5bc61"
23902448
dependencies = [
23912449
"h2",
23922450
"http",
@@ -2530,6 +2588,12 @@ dependencies = [
25302588
"libc",
25312589
]
25322590

2591+
[[package]]
2592+
name = "no-std-compat"
2593+
version = "0.4.1"
2594+
source = "registry+https://github.com/rust-lang/crates.io-index"
2595+
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
2596+
25332597
[[package]]
25342598
name = "nom"
25352599
version = "7.1.3"
@@ -2540,6 +2604,12 @@ dependencies = [
25402604
"minimal-lexical",
25412605
]
25422606

2607+
[[package]]
2608+
name = "nonzero_ext"
2609+
version = "0.3.0"
2610+
source = "registry+https://github.com/rust-lang/crates.io-index"
2611+
checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
2612+
25432613
[[package]]
25442614
name = "nu-ansi-term"
25452615
version = "0.46.0"
@@ -2764,6 +2834,12 @@ version = "0.1.0"
27642834
source = "registry+https://github.com/rust-lang/crates.io-index"
27652835
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
27662836

2837+
[[package]]
2838+
name = "portable-atomic"
2839+
version = "1.7.0"
2840+
source = "registry+https://github.com/rust-lang/crates.io-index"
2841+
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
2842+
27672843
[[package]]
27682844
name = "powerfmt"
27692845
version = "0.2.0"
@@ -2920,6 +2996,21 @@ dependencies = [
29202996
"prost",
29212997
]
29222998

2999+
[[package]]
3000+
name = "quanta"
3001+
version = "0.12.3"
3002+
source = "registry+https://github.com/rust-lang/crates.io-index"
3003+
checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
3004+
dependencies = [
3005+
"crossbeam-utils",
3006+
"libc",
3007+
"once_cell",
3008+
"raw-cpuid",
3009+
"wasi",
3010+
"web-sys",
3011+
"winapi",
3012+
]
3013+
29233014
[[package]]
29243015
name = "quick-error"
29253016
version = "1.2.3"
@@ -2980,6 +3071,15 @@ version = "1.5.1"
29803071
source = "registry+https://github.com/rust-lang/crates.io-index"
29813072
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
29823073

3074+
[[package]]
3075+
name = "raw-cpuid"
3076+
version = "11.1.0"
3077+
source = "registry+https://github.com/rust-lang/crates.io-index"
3078+
checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d"
3079+
dependencies = [
3080+
"bitflags 2.4.2",
3081+
]
3082+
29833083
[[package]]
29843084
name = "rcgen"
29853085
version = "0.12.1"
@@ -3290,6 +3390,15 @@ version = "0.9.8"
32903390
source = "registry+https://github.com/rust-lang/crates.io-index"
32913391
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
32923392

3393+
[[package]]
3394+
name = "spinning_top"
3395+
version = "0.3.0"
3396+
source = "registry+https://github.com/rust-lang/crates.io-index"
3397+
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
3398+
dependencies = [
3399+
"lock_api",
3400+
]
3401+
32933402
[[package]]
32943403
name = "stable_deref_trait"
32953404
version = "1.2.0"
@@ -3864,6 +3973,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
38643973
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
38653974

38663975
[[package]]
3976+
name = "web-sys"
3977+
version = "0.3.70"
3978+
source = "registry+https://github.com/rust-lang/crates.io-index"
3979+
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
3980+
dependencies = [
3981+
"js-sys",
3982+
"wasm-bindgen",
3983+
]
3984+
3985+
[[package]]
3986+
>>>>>>> dca153b2 (wip)
38673987
name = "widestring"
38683988
version = "1.1.0"
38693989
source = "registry+https://github.com/rust-lang/crates.io-index"

linkerd/app/core/src/errors/respond.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ impl SyntheticHttpResponse {
166166
}
167167
}
168168

169+
pub fn rate_limited(msg: impl ToString) -> Self {
170+
Self {
171+
http_status: http::StatusCode::TOO_MANY_REQUESTS,
172+
grpc_status: tonic::Code::ResourceExhausted,
173+
close_connection: false,
174+
message: Cow::Owned(msg.to_string()),
175+
location: None,
176+
}
177+
}
178+
169179
pub fn loop_detected(msg: impl ToString) -> Self {
170180
Self {
171181
http_status: http::StatusCode::LOOP_DETECTED,

linkerd/app/inbound/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ test-util = [
2121
bytes = "1"
2222
http = "0.2"
2323
futures = { version = "0.3", default-features = false }
24+
governor = { version = "0.6", features = ["std"] }
2425
linkerd-app-core = { path = "../core" }
2526
linkerd-app-test = { path = "../test", optional = true }
27+
linkerd-dns-name = { path = "../../dns/name" }
28+
linkerd-error = { path = "../../error" }
29+
linkerd-identity = { path = "../../identity" }
2630
linkerd-http-access-log = { path = "../../http/access-log" }
2731
linkerd-idle-cache = { path = "../../idle-cache" }
2832
linkerd-meshtls = { path = "../../meshtls", optional = true }

linkerd/app/inbound/src/http.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
mod router;
1+
pub mod router;
22
mod server;
33
mod set_identity_header;
44
#[cfg(test)]

linkerd/app/inbound/src/http/router.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{policy, stack_labels, Inbound};
1+
use crate::{/*limit, */policy, stack_labels, Inbound};
22
use linkerd_app_core::{
33
classify, errors, http_tracing, metrics, profiles,
44
proxy::{http, tap},
@@ -241,6 +241,7 @@ impl<C> Inbound<C> {
241241
.check_new_service::<(policy::HttpRoutePermit, T), http::Request<http::BoxBody>>()
242242
.push(svc::ArcNewService::layer())
243243
.push(policy::NewHttpPolicy::layer(rt.metrics.http_authz.clone()))
244+
//.push(limit::NewRateLimitPolicy::layer())
244245
// Used by tap.
245246
.push_http_insert_target::<tls::ConditionalServerTls>()
246247
.push_http_insert_target::<Remote<ClientAddr>>()

linkerd/app/inbound/src/http/server.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ impl errors::HttpRescue<Error> for ServerRescue {
203203
));
204204
}
205205

206+
if errors::is_caused_by::<policy::http::RateLimitError>(&*error) {
207+
return Ok(errors::SyntheticHttpResponse::rate_limited(error));
208+
}
209+
206210
if errors::is_caused_by::<crate::GatewayDomainInvalid>(&*error) {
207211
return Ok(errors::SyntheticHttpResponse::not_found(error));
208212
}

linkerd/app/inbound/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod accept;
1111
mod detect;
1212
pub mod direct;
1313
mod http;
14+
mod limit;
1415
mod metrics;
1516
pub mod policy;
1617
mod server;

0 commit comments

Comments
 (0)