176 lines
5.3 KiB
Rust
176 lines
5.3 KiB
Rust
// 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<JurisdictionId, ResourceQuota>,
|
||
/// 当前分配
|
||
allocations: HashMap<JurisdictionId, ResourceAllocation>,
|
||
}
|
||
|
||
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::<u64>()
|
||
+ 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<ResourceAllocation, String> {
|
||
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<JurisdictionId> {
|
||
// 返回资源使用超过配额的辖区
|
||
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<ResourceAlert> {
|
||
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,
|
||
}
|