-
Notifications
You must be signed in to change notification settings - Fork 456
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
proxy: cull http connections (#7632)
## Problem Some HTTP client connections can stay open for quite a long time. ## Summary of changes When there are too many HTTP client connections, pick a random connection and gracefully cancel it.
- Loading branch information
1 parent
0af66a6
commit 0c99e5e
Showing
10 changed files
with
164 additions
and
18 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
//! A set for cancelling random http connections | ||
use std::{ | ||
hash::{BuildHasher, BuildHasherDefault}, | ||
num::NonZeroUsize, | ||
time::Duration, | ||
}; | ||
|
||
use indexmap::IndexMap; | ||
use parking_lot::Mutex; | ||
use rand::{thread_rng, Rng}; | ||
use rustc_hash::FxHasher; | ||
use tokio::time::Instant; | ||
use tokio_util::sync::CancellationToken; | ||
use uuid::Uuid; | ||
|
||
type Hasher = BuildHasherDefault<FxHasher>; | ||
|
||
pub struct CancelSet { | ||
shards: Box<[Mutex<CancelShard>]>, | ||
// keyed by random uuid, fxhasher is fine | ||
hasher: Hasher, | ||
} | ||
|
||
pub struct CancelShard { | ||
tokens: IndexMap<uuid::Uuid, (Instant, CancellationToken), Hasher>, | ||
} | ||
|
||
impl CancelSet { | ||
pub fn new(shards: usize) -> Self { | ||
CancelSet { | ||
shards: (0..shards) | ||
.map(|_| { | ||
Mutex::new(CancelShard { | ||
tokens: IndexMap::with_hasher(Hasher::default()), | ||
}) | ||
}) | ||
.collect(), | ||
hasher: Hasher::default(), | ||
} | ||
} | ||
|
||
pub fn take(&self) -> Option<CancellationToken> { | ||
for _ in 0..4 { | ||
if let Some(token) = self.take_raw(thread_rng().gen()) { | ||
return Some(token); | ||
} | ||
tracing::trace!("failed to get cancel token"); | ||
} | ||
None | ||
} | ||
|
||
pub fn take_raw(&self, rng: usize) -> Option<CancellationToken> { | ||
NonZeroUsize::new(self.shards.len()) | ||
.and_then(|len| self.shards[rng % len].lock().take(rng / len)) | ||
} | ||
|
||
pub fn insert(&self, id: uuid::Uuid, token: CancellationToken) -> CancelGuard<'_> { | ||
let shard = NonZeroUsize::new(self.shards.len()).map(|len| { | ||
let hash = self.hasher.hash_one(id) as usize; | ||
let shard = &self.shards[hash % len]; | ||
shard.lock().insert(id, token); | ||
shard | ||
}); | ||
CancelGuard { shard, id } | ||
} | ||
} | ||
|
||
impl CancelShard { | ||
fn take(&mut self, rng: usize) -> Option<CancellationToken> { | ||
NonZeroUsize::new(self.tokens.len()).and_then(|len| { | ||
// 10 second grace period so we don't cancel new connections | ||
if self.tokens.get_index(rng % len)?.1 .0.elapsed() < Duration::from_secs(10) { | ||
return None; | ||
} | ||
|
||
let (_key, (_insert, token)) = self.tokens.swap_remove_index(rng % len)?; | ||
Some(token) | ||
}) | ||
} | ||
|
||
fn remove(&mut self, id: uuid::Uuid) { | ||
self.tokens.swap_remove(&id); | ||
} | ||
|
||
fn insert(&mut self, id: uuid::Uuid, token: CancellationToken) { | ||
self.tokens.insert(id, (Instant::now(), token)); | ||
} | ||
} | ||
|
||
pub struct CancelGuard<'a> { | ||
shard: Option<&'a Mutex<CancelShard>>, | ||
id: Uuid, | ||
} | ||
|
||
impl Drop for CancelGuard<'_> { | ||
fn drop(&mut self) { | ||
if let Some(shard) = self.shard { | ||
shard.lock().remove(self.id); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0c99e5e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3135 tests run: 2988 passed, 1 failed, 146 skipped (full report)
Failures on Postgres 14
test_storage_controller_many_tenants[github-actions-selfhosted]
: releaseFlaky tests (3)
Postgres 16
test_gc_aggressive
: debugtest_vm_bit_clear_on_heap_lock
: debugPostgres 15
test_vm_bit_clear_on_heap_lock
: debugCode coverage* (full report)
functions
:31.2% (6258 of 20043 functions)
lines
:46.7% (46950 of 100468 lines)
* collected from Rust tests only
0c99e5e at 2024-05-08T06:35:30.570Z :recycle: