refactor: batch cluster lock and health readiness (#3936)

This commit is contained in:
Zhengchao An
2026-06-27 10:51:06 +08:00
committed by GitHub
parent 675597ec16
commit e1a4b9e0b6
9 changed files with 312 additions and 59 deletions
+5
View File
@@ -48,3 +48,8 @@ pub const DEFAULT_HEALTH_COMPAT_BUSY_MAX_ACTIVE_REQUESTS: usize = 0;
/// in running state if a global KMS manager exists.
pub const ENV_HEALTH_COMPAT_KMS_READY_CHECK_ENABLE: &str = "RUSTFS_HEALTH_COMPAT_KMS_READY_CHECK_ENABLE";
pub const DEFAULT_HEALTH_COMPAT_KMS_READY_CHECK_ENABLE: bool = false;
/// Enable peer-health readiness impact.
/// When disabled, peer-health state is reported but does not affect readiness.
pub const ENV_HEALTH_PEER_READY_CHECK_ENABLE: &str = "RUSTFS_HEALTH_PEER_READY_CHECK_ENABLE";
pub const DEFAULT_HEALTH_PEER_READY_CHECK_ENABLE: bool = false;
+5 -14
View File
@@ -46,7 +46,6 @@ use rustfs_common::heal_channel::HealOpts;
use rustfs_common::heal_channel::{DriveState, HealItemType};
use rustfs_filemeta::FileInfo;
use rustfs_lock::NamespaceLockWrapper;
use rustfs_lock::client::LockClient;
use rustfs_madmin::heal_commands::{HealDriveInfo, HealResultItem};
use rustfs_utils::{crc_hash, path::path_join_buf, sip_hash};
use std::{collections::HashMap, sync::Arc};
@@ -102,28 +101,17 @@ impl Sets {
let mut disk_set = Vec::with_capacity(set_count);
// Get lock clients from global storage
let lock_clients = runtime_sources::global_lock_clients();
let lock_registry = runtime_sources::lock_registry();
for i in 0..set_count {
let mut set_drive = Vec::with_capacity(set_drive_count);
let mut set_endpoints = Vec::with_capacity(set_drive_count);
let mut set_lock_clients: HashMap<String, Arc<dyn LockClient>> = HashMap::new();
for j in 0..set_drive_count {
let idx = i * set_drive_count + j;
let mut disk = disks[idx].clone();
let endpoint = endpoints.endpoints.as_ref()[idx].clone();
if let Some(lock_clients_map) = lock_clients {
let host_port = endpoint.host_port();
if let Some(lock_client) = lock_clients_map.get(&host_port)
&& !set_lock_clients.contains_key(&host_port)
{
set_lock_clients.insert(host_port, lock_client.clone());
}
}
set_endpoints.push(endpoint);
if disk.is_none() {
@@ -164,7 +152,10 @@ impl Sets {
}
}
let lockers = set_lock_clients.values().cloned().collect::<Vec<Arc<dyn LockClient>>>();
let lockers = lock_registry
.as_ref()
.map(|registry| registry.clients_for_endpoints(&set_endpoints))
.unwrap_or_default();
let set_disks = SetDisks::new(
runtime_sources::local_node_name().await,
Arc::new(RwLock::new(set_drive)),
+75 -1
View File
@@ -13,7 +13,7 @@
// limitations under the License.
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
sync::{Arc, OnceLock},
time::SystemTime,
};
@@ -59,6 +59,35 @@ const TEST_RPC_SECRET: &str = "test-rpc-secret";
pub(crate) type WorkloadSnapshotProviderRef = Arc<dyn WorkloadAdmissionSnapshotProvider + Send + Sync>;
#[derive(Clone, Default)]
pub(crate) struct LockRegistry {
clients: HashMap<String, Arc<dyn LockClient>>,
}
impl LockRegistry {
pub(crate) fn new(clients: HashMap<String, Arc<dyn LockClient>>) -> Self {
Self { clients }
}
pub(crate) fn clients_for_endpoints(&self, endpoints: &[Endpoint]) -> Vec<Arc<dyn LockClient>> {
let mut seen_hosts = HashSet::with_capacity(endpoints.len());
let mut clients = Vec::with_capacity(endpoints.len());
for endpoint in endpoints {
let host_port = endpoint.host_port();
if host_port.is_empty() || !seen_hosts.insert(host_port.clone()) {
continue;
}
if let Some(client) = self.clients.get(&host_port) {
clients.push(client.clone());
}
}
clients
}
}
static WORKLOAD_ADMISSION_SNAPSHOT_PROVIDER: OnceLock<WorkloadSnapshotProviderRef> = OnceLock::new();
pub(crate) fn set_workload_admission_snapshot_provider(
@@ -256,6 +285,11 @@ pub(crate) fn global_lock_clients() -> Option<&'static HashMap<String, Arc<dyn L
get_global_lock_clients()
}
pub(crate) fn lock_registry() -> Option<LockRegistry> {
global_lock_clients()
.map(|clients| LockRegistry::new(clients.iter().map(|(host, client)| (host.clone(), client.clone())).collect()))
}
pub(crate) fn set_primary_lock_client(client: Arc<dyn LockClient>) -> std::result::Result<(), Arc<dyn LockClient>> {
set_global_lock_client(client)
}
@@ -469,3 +503,43 @@ pub(crate) async fn initialize_local_disk_maps(endpoint_pools: EndpointServerPoo
pub(crate) async fn init_tier_config_mgr(store: Arc<ECStore>) -> Result<()> {
GLOBAL_TierConfigMgr.write().await.init(store).await
}
#[cfg(test)]
mod tests {
use super::LockRegistry;
use crate::disk::endpoint::Endpoint;
use rustfs_lock::{LocalClient, LockClient};
use std::{collections::HashMap, sync::Arc};
fn url_endpoint(raw: &str) -> Endpoint {
Endpoint {
url: url::Url::parse(raw).expect("test endpoint url"),
is_local: false,
pool_idx: 0,
set_idx: 0,
disk_idx: 0,
}
}
#[test]
fn lock_registry_selects_unique_clients_in_endpoint_order() {
let client_a: Arc<dyn LockClient> = Arc::new(LocalClient::new());
let client_b: Arc<dyn LockClient> = Arc::new(LocalClient::new());
let registry = LockRegistry::new(HashMap::from([
("node-a:9000".to_string(), client_a.clone()),
("node-b:9000".to_string(), client_b.clone()),
]));
let endpoints = vec![
url_endpoint("http://node-a:9000/data-a"),
url_endpoint("http://node-a:9000/data-b"),
url_endpoint("http://node-missing:9000/data"),
url_endpoint("http://node-b:9000/data"),
];
let clients = registry.clients_for_endpoints(&endpoints);
assert_eq!(clients.len(), 2);
assert!(Arc::ptr_eq(&clients[0], &client_a));
assert!(Arc::ptr_eq(&clients[1], &client_b));
}
}