mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
perf(protos): cache internode msgpack-only flag (#5191)
Cache the internode msgpack-only env gate after the first read so metadata RPC send paths avoid repeated environment parsing. Keep a reset hook for tests that intentionally change the env in-process. Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
Generated
+1
@@ -9748,6 +9748,7 @@ dependencies = [
|
|||||||
"rustfs-utils",
|
"rustfs-utils",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"temp-env",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tonic-prost",
|
"tonic-prost",
|
||||||
|
|||||||
@@ -3018,15 +3018,32 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compat_json_dual_writes_by_default() {
|
fn compat_json_dual_writes_by_default() {
|
||||||
let resp = sample_read_multiple_resp("file", b"data");
|
with_internode_msgpack_env(
|
||||||
let json = compat_json(&resp).expect("compat_json should encode");
|
[
|
||||||
assert!(!json.is_empty());
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, None::<&str>),
|
||||||
assert_eq!(json, serde_json::to_string(&resp).expect("json should encode"));
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
||||||
|
],
|
||||||
|
|| {
|
||||||
|
let resp = sample_read_multiple_resp("file", b"data");
|
||||||
|
let json = compat_json(&resp).expect("compat_json should encode");
|
||||||
|
assert!(!json.is_empty());
|
||||||
|
assert_eq!(json, serde_json::to_string(&resp).expect("json should encode"));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_internode_msgpack_env<R>(vars: [(&'static str, Option<&'static str>); 2], f: impl FnOnce() -> R) -> R {
|
||||||
|
temp_env::with_vars(vars, || {
|
||||||
|
rustfs_protos::reset_internode_rpc_msgpack_only_cache();
|
||||||
|
let result = f();
|
||||||
|
rustfs_protos::reset_internode_rpc_msgpack_only_cache();
|
||||||
|
result
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compat_json_keeps_json_when_msgpack_only_lacks_fleet_confirmation() {
|
fn compat_json_keeps_json_when_msgpack_only_lacks_fleet_confirmation() {
|
||||||
temp_env::with_vars(
|
with_internode_msgpack_env(
|
||||||
[
|
[
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
||||||
@@ -3043,7 +3060,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compat_json_omits_json_only_after_fleet_confirmation() {
|
fn compat_json_omits_json_only_after_fleet_confirmation() {
|
||||||
temp_env::with_vars(
|
with_internode_msgpack_env(
|
||||||
[
|
[
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, Some("true")),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, Some("true")),
|
||||||
|
|||||||
@@ -54,3 +54,4 @@ doctest = false
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
temp-env = { workspace = true }
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use std::{
|
|||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
error::Error,
|
error::Error,
|
||||||
sync::LazyLock,
|
sync::LazyLock,
|
||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicU8, AtomicUsize, Ordering},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
@@ -54,7 +54,11 @@ pub const DEFAULT_GRPC_SERVER_MESSAGE_LEN: usize = 100 * 1024 * 1024;
|
|||||||
/// Default value: https://
|
/// Default value: https://
|
||||||
const RUSTFS_HTTPS_PREFIX: &str = "https://";
|
const RUSTFS_HTTPS_PREFIX: &str = "https://";
|
||||||
const TLS_GENERATION_CACHE_MAX_SIZE: usize = 512;
|
const TLS_GENERATION_CACHE_MAX_SIZE: usize = 512;
|
||||||
|
const INTERNODE_RPC_MSGPACK_ONLY_CACHE_UNSET: u8 = 0;
|
||||||
|
const INTERNODE_RPC_MSGPACK_ONLY_CACHE_FALSE: u8 = 1;
|
||||||
|
const INTERNODE_RPC_MSGPACK_ONLY_CACHE_TRUE: u8 = 2;
|
||||||
static TLS_GENERATION_CACHE: LazyLock<Mutex<HashMap<String, u64>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
|
static TLS_GENERATION_CACHE: LazyLock<Mutex<HashMap<String, u64>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
|
||||||
|
static INTERNODE_RPC_MSGPACK_ONLY_CACHE: AtomicU8 = AtomicU8::new(INTERNODE_RPC_MSGPACK_ONLY_CACHE_UNSET);
|
||||||
|
|
||||||
fn enforce_tls_generation_cache_bound(generation_cache: &mut HashMap<String, u64>, generation: u64, addr: &str) {
|
fn enforce_tls_generation_cache_bound(generation_cache: &mut HashMap<String, u64>, generation: u64, addr: &str) {
|
||||||
if generation_cache.len() < TLS_GENERATION_CACHE_MAX_SIZE || generation_cache.contains_key(addr) {
|
if generation_cache.len() < TLS_GENERATION_CACHE_MAX_SIZE || generation_cache.contains_key(addr) {
|
||||||
@@ -642,13 +646,33 @@ mod tier_mutation_rpc_tests {
|
|||||||
/// decode the compatibility field. Operators must also set the fleet-confirmed guard after the
|
/// decode the compatibility field. Operators must also set the fleet-confirmed guard after the
|
||||||
/// convergence runbook proves every peer supports `_bin` and rollback.
|
/// convergence runbook proves every peer supports `_bin` and rollback.
|
||||||
pub fn internode_rpc_msgpack_only() -> bool {
|
pub fn internode_rpc_msgpack_only() -> bool {
|
||||||
rustfs_utils::get_env_bool(
|
match INTERNODE_RPC_MSGPACK_ONLY_CACHE.load(Ordering::Acquire) {
|
||||||
|
INTERNODE_RPC_MSGPACK_ONLY_CACHE_FALSE => return false,
|
||||||
|
INTERNODE_RPC_MSGPACK_ONLY_CACHE_TRUE => return true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let enabled = rustfs_utils::get_env_bool(
|
||||||
rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY,
|
rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY,
|
||||||
rustfs_config::DEFAULT_INTERNODE_RPC_MSGPACK_ONLY,
|
rustfs_config::DEFAULT_INTERNODE_RPC_MSGPACK_ONLY,
|
||||||
) && rustfs_utils::get_env_bool(
|
) && rustfs_utils::get_env_bool(
|
||||||
rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED,
|
rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED,
|
||||||
rustfs_config::DEFAULT_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED,
|
rustfs_config::DEFAULT_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED,
|
||||||
)
|
);
|
||||||
|
INTERNODE_RPC_MSGPACK_ONLY_CACHE.store(
|
||||||
|
if enabled {
|
||||||
|
INTERNODE_RPC_MSGPACK_ONLY_CACHE_TRUE
|
||||||
|
} else {
|
||||||
|
INTERNODE_RPC_MSGPACK_ONLY_CACHE_FALSE
|
||||||
|
},
|
||||||
|
Ordering::Release,
|
||||||
|
);
|
||||||
|
enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn reset_internode_rpc_msgpack_only_cache() {
|
||||||
|
INTERNODE_RPC_MSGPACK_ONLY_CACHE.store(INTERNODE_RPC_MSGPACK_ONLY_CACHE_UNSET, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consecutive-failure threshold after which an internode peer is marked offline (grpc-optimization
|
/// Consecutive-failure threshold after which an internode peer is marked offline (grpc-optimization
|
||||||
@@ -951,6 +975,35 @@ mod tests {
|
|||||||
assert!(bulk_channel_pool_size() >= 1);
|
assert!(bulk_channel_pool_size() >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn internode_rpc_msgpack_only_reuses_cached_env_until_reset() {
|
||||||
|
reset_internode_rpc_msgpack_only_cache();
|
||||||
|
|
||||||
|
temp_env::with_vars(
|
||||||
|
[
|
||||||
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||||
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, Some("true")),
|
||||||
|
],
|
||||||
|
|| {
|
||||||
|
assert!(internode_rpc_msgpack_only());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
temp_env::with_vars(
|
||||||
|
[
|
||||||
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, None::<&str>),
|
||||||
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
||||||
|
],
|
||||||
|
|| {
|
||||||
|
assert!(internode_rpc_msgpack_only(), "cached value should avoid repeated env reads");
|
||||||
|
reset_internode_rpc_msgpack_only_cache();
|
||||||
|
assert!(!internode_rpc_msgpack_only(), "reset must reload current env values");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
reset_internode_rpc_msgpack_only_cache();
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_channel_for_class_bulk_reuses_control_cache_when_isolation_disabled() {
|
async fn get_channel_for_class_bulk_reuses_control_cache_when_isolation_disabled() {
|
||||||
// Isolation defaults off, so a Bulk request must reuse the control channel keyed by the
|
// Isolation defaults off, so a Bulk request must reuse the control channel keyed by the
|
||||||
|
|||||||
@@ -1215,9 +1215,18 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_internode_msgpack_env<R>(vars: [(&'static str, Option<&'static str>); 2], f: impl FnOnce() -> R) -> R {
|
||||||
|
temp_env::with_vars(vars, || {
|
||||||
|
rustfs_protos::reset_internode_rpc_msgpack_only_cache();
|
||||||
|
let result = f();
|
||||||
|
rustfs_protos::reset_internode_rpc_msgpack_only_cache();
|
||||||
|
result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compat_response_json_keeps_json_when_msgpack_only_lacks_fleet_confirmation() {
|
fn compat_response_json_keeps_json_when_msgpack_only_lacks_fleet_confirmation() {
|
||||||
temp_env::with_vars(
|
with_internode_msgpack_env(
|
||||||
[
|
[
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
||||||
@@ -1237,7 +1246,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compat_response_json_omits_json_only_after_fleet_confirmation() {
|
fn compat_response_json_omits_json_only_after_fleet_confirmation() {
|
||||||
temp_env::with_vars(
|
with_internode_msgpack_env(
|
||||||
[
|
[
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, Some("true")),
|
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, Some("true")),
|
||||||
|
|||||||
Reference in New Issue
Block a user