// nac-multi-jurisdiction/src/resource_sharing.rs // Issue #59: 物理资源共享与公平分配 use std::collections::HashMap; use serde::{Serialize, Deserialize}; use crate::jurisdiction::JurisdictionId; /// 资源配额(每辖区) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ResourceQuota { pub jurisdiction_id: JurisdictionId, /// CPU 共享比例,定点数 1e4(2500 = 25.00%) pub cpu_share: u64, /// 内存共享比例,定点数 1e4 pub memory_share: u64, /// 带宽共享比例,定点数 1e4 pub bandwidth_share: u64, /// 存储共享比例,定点数 1e4 pub storage_share: u64, } impl ResourceQuota { /// 验证配额合法性(各项不超过 100%) pub fn is_valid(&self) -> bool { self.cpu_share <= 10000 && self.memory_share <= 10000 && self.bandwidth_share <= 10000 && self.storage_share <= 10000 } /// 计算总资源占用(平均值) pub fn total_share(&self) -> u64 { (self.cpu_share + self.memory_share + self.bandwidth_share + self.storage_share) / 4 } } /// 资源分配记录 #[derive(Debug, Clone)] pub struct ResourceAllocation { pub jurisdiction_id: JurisdictionId, pub allocated_cpu: u64, // 毫核 pub allocated_memory: u64, // MB pub allocated_bandwidth: u64, // Mbps pub allocated_storage: u64, // GB pub timestamp: u64, } /// 资源池(物理共享层) pub struct ResourcePool { /// 总 CPU(毫核) total_cpu: u64, /// 总内存(MB) total_memory: u64, /// 总带宽(Mbps) total_bandwidth: u64, /// 总存储(GB) total_storage: u64, /// 各辖区配额 quotas: HashMap, /// 当前分配 allocations: HashMap, } impl ResourcePool { pub fn new(cpu: u64, memory: u64, bandwidth: u64, storage: u64) -> Self { ResourcePool { total_cpu: cpu, total_memory: memory, total_bandwidth: bandwidth, total_storage: storage, quotas: HashMap::new(), allocations: HashMap::new(), } } /// 设置辖区资源配额 pub fn set_quota(&mut self, quota: ResourceQuota) -> Result<(), String> { if !quota.is_valid() { return Err("资源配额无效".to_string()); } // 检查总配额不超过 100% let total_cpu: u64 = self.quotas.values().map(|q| q.cpu_share).sum::() + quota.cpu_share; if total_cpu > 10000 { return Err("CPU 总配额超过 100%".to_string()); } self.quotas.insert(quota.jurisdiction_id.clone(), quota); Ok(()) } /// 为辖区分配资源 pub fn allocate(&mut self, jid: &JurisdictionId, timestamp: u64) -> Result { let quota = self.quotas.get(jid) .ok_or_else(|| format!("辖区 {} 没有配额", jid.as_str()))?; let allocation = ResourceAllocation { jurisdiction_id: jid.clone(), allocated_cpu: self.total_cpu * quota.cpu_share / 10000, allocated_memory: self.total_memory * quota.memory_share / 10000, allocated_bandwidth: self.total_bandwidth * quota.bandwidth_share / 10000, allocated_storage: self.total_storage * quota.storage_share / 10000, timestamp, }; self.allocations.insert(jid.clone(), allocation.clone()); Ok(allocation) } /// 获取辖区当前分配 pub fn get_allocation(&self, jid: &JurisdictionId) -> Option<&ResourceAllocation> { self.allocations.get(jid) } /// 检查是否存在资源抢占 pub fn check_contention(&self) -> Vec { // 返回资源使用超过配额的辖区 self.allocations.iter() .filter(|(jid, alloc)| { if let Some(quota) = self.quotas.get(*jid) { let used_cpu = alloc.allocated_cpu * 10000 / self.total_cpu; used_cpu > quota.cpu_share + 500 // 超出 5% 视为抢占 } else { false } }) .map(|(jid, _)| jid.clone()) .collect() } } /// 资源监控器 pub struct ResourceMonitor { pool: ResourcePool, alert_threshold: u64, // 超过配额多少时告警,定点数 1e4 } impl ResourceMonitor { pub fn new(pool: ResourcePool) -> Self { ResourceMonitor { pool, alert_threshold: 1000, // 超出 10% 告警 } } /// 检查所有辖区资源使用情况 pub fn check_all(&self) -> Vec { let contention = self.pool.check_contention(); contention.into_iter().map(|jid| ResourceAlert { jurisdiction_id: jid, alert_type: AlertType::ResourceContention, severity: AlertSeverity::Warning, }).collect() } } #[derive(Debug, Clone)] pub struct ResourceAlert { pub jurisdiction_id: JurisdictionId, pub alert_type: AlertType, pub severity: AlertSeverity, } #[derive(Debug, Clone, PartialEq)] pub enum AlertType { ResourceContention, QuotaExceeded, PoolExhausted, } #[derive(Debug, Clone, PartialEq)] pub enum AlertSeverity { Info, Warning, Critical, }