跳到主内容

v0.46.0 版本说明

版本说明

EnerOS v0.46.0 版本说明

  • 发布日期:2026-07-03
  • 版本代号:Stable
  • 支持状态:稳定(Stable),长期支持候选
  • Crate 总数:55
  • 测试用例数:7200+
  • 贡献者:30 人

版本概述

EnerOS v0.46.0 是「成熟优化」阶段的第六个版本,聚焦稳定性增强。在前五个版本完成性能基准、安全审计、开发者体验、文档系统与生态扩展后,本版本回归工程本质,集中精力解决长时间运行下的稳定性问题,为 v0.47.0 的最终收敛奠定坚实基础。

电力系统对可用性的要求极为严苛,省级调度中心要求系统年可用性达到 99.999%(即全年停机不超过 5 分钟)。这意味着 EnerOS 必须在长时间连续运行(数月乃至数年)下保持内存稳定、性能不退化、错误可恢复。v0.46.0 通过系统化的压力测试发现了 23 个内存泄漏点、12 个错误处理缺陷与 8 个资源未释放问题,并全部修复。

本版本引入了自动化压力测试框架 eneros-stress,能在 24 小时内模拟 7 天的真实负载,通过加速时钟与注入故障验证系统的长期稳定性。所有压力测试在 CI 中以周为周期运行,确保每次提交不会引入新的稳定性问题。

关键数据

指标数值说明
Crate 数量55新增 eneros-stress
测试用例7200+含 180+ 压力测试
内存泄漏修复23 处全部已修复
错误处理缺陷修复12 处全部已修复
连续运行测试168 小时无退化
内存增长(24h)< 0.1%满载运行
可用性目标99.999%年停机 < 5 分钟

新特性

1. 压力测试框架

新增 eneros-stress crate,提供系统化的压力测试能力。框架支持负载生成、故障注入、加速时钟与资源监控,能在短时间内模拟长时间运行场景。

框架架构

eneros-stress/
├── src/
│   ├── generator/        # 负载生成器
│   │   ├── topology.rs   # 拓扑操作负载
│   │   ├── powerflow.rs  # 潮流计算负载
│   │   ├── timeseries.rs # 时序写入负载
│   │   └── agent.rs      # Agent 消息负载
│   ├── injector/         # 故障注入器
│   │   ├── network.rs    # 网络故障
│   │   ├── disk.rs       # 磁盘故障
│   │   └── process.rs    # 进程故障
│   ├── monitor/          # 资源监控
│   │   ├── memory.rs     # 内存增长检测
│   │   ├── fd.rs         # 文件描述符泄漏
│   │   └── thread.rs     # 线程泄漏
│   └── clock/            # 加速时钟

使用示例

use eneros_stress::{StressTest, StressConfig, LoadProfile, FaultInjector};
use std::time::Duration;

let stress = StressTest::new(StressConfig {
    duration: Duration::from_secs(86400 * 7),     // 模拟 7 天
    accelerated_clock: 24.0,                       // 24 倍加速,实际运行 7 小时
    load_profile: LoadProfile::Realistic {
        peak_times: vec![8, 12, 18],               // 每日高峰时段
        base_load: 0.3,                            // 基础负载 30%
        peak_load: 0.95,                           // 峰值负载 95%
    },
    fault_injection: FaultInjector::Chaos {
        network_partition_prob: 0.001,             // 0.1% 网络分区
        disk_full_prob: 0.0005,                    // 0.05% 磁盘满
        process_kill_prob: 0.002,                  // 0.2% 进程杀死
    },
    memory_leak_threshold: Duration::from_secs(3600), // 1 小时后检测
});

let report = stress.run().await?;

println!("测试结果:");
println!("  总操作数: {}", report.total_ops);
println!("  错误数: {}", report.errors.len());
println!("  内存增长: {:.2}%", report.memory_growth_pct);
println!("  可用性: {:.4}%", report.availability * 100.0);

for leak in &report.memory_leaks {
    println!("  内存泄漏: {} (增长 {:.2} MB/h)", leak.location, leak.rate_mb_per_hour);
}

压力测试场景

场景负载模式故障注入持续时间验证目标
满载运行100% 持续168 小时内存稳定
峰谷波动真实负载曲线7 天(加速)性能不退化
混沌工程真实负载网络分区24 小时故障恢复
资源耗尽递增负载磁盘满12 小时优雅降级
长时连接持续连接进程杀死48 小时重连恢复

2. 内存泄漏修复

通过压力测试发现并修复了 23 处内存泄漏,涵盖拓扑快照、Agent 上下文、时序缓存、约束引擎与审计链五个模块。

主要泄漏点

模块泄漏原因影响速率修复方式
eneros-topology快照未释放2.3 MB/h引用计数 + Drop
eneros-agent上下文缓存累积1.8 MB/hLRU 淘汰
eneros-timeseries压缩缓冲区未回收5.1 MB/h分级落盘
eneros-constraint约束快照历史0.7 MB/h限制历史深度
eneros-trust审计日志缓冲3.2 MB/h定期 flush
eneros-memoryAgent 记忆向量4.5 MB/h分层压缩
eneros-orchestratorDAG 节点缓存1.2 MB/h执行后清理

内存监控工具

use eneros_stress::monitor::{MemoryMonitor, LeakDetector};

let monitor = MemoryMonitor::new()
    .sample_interval(Duration::from_secs(60))
    .leak_detector(LeakDetector::LinearRegression {
        min_samples: 60,           // 至少 60 个样本(1 小时)
        growth_threshold: 0.1,     // 每小时增长 > 0.1% 报警
    });

monitor.start().await?;

// 获取内存报告
let snapshot = monitor.snapshot().await?;
println!("当前 RSS: {:.1} MB", snapshot.rss_mb);
println!("24 小时增长: {:.2}%", snapshot.growth_24h_pct);

// 检测泄漏
if let Some(leaks) = monitor.detect_leaks().await? {
    for leak in leaks {
        eprintln!("疑似泄漏: {} 增长 {:.2} MB/h", leak.location, leak.rate);
    }
}

3. 长时间运行优化

针对长时间运行场景进行了多项优化,确保系统在连续运行数月后性能不退化。

快照历史深度限制

use eneros_topology::{TopologyConfig, SnapshotPolicy};

let config = TopologyConfig {
    snapshot_policy: SnapshotPolicy::Bounded {
        max_history: 1000,                          // 最多保留 1000 个快照
        max_age: Duration::from_secs(3600),         // 最长保留 1 小时
        eviction: EvictionPolicy::OldestFirst,
    },
    ..Default::default()
};

Agent 上下文 LRU 淘汰

use eneros_agent::{AgentRuntime, CacheConfig};

let runtime = AgentRuntime::new(CacheConfig {
    max_contexts: 500,                               // 最多缓存 500 个上下文
    context_ttl: Duration::from_secs(300),           // 5 分钟未使用即淘汰
    eviction: EvictionPolicy::LRU,
});

时序数据分级落盘

use eneros_timeseries::{TsdbConfig, FlushPolicy};

let config = TsdbConfig {
    flush_policy: FlushPolicy::Tiered {
        hot_tier_size: 8 * 1024 * 1024,              // 热层 8MB
        warm_tier_size: 64 * 1024 * 1024,            // 温层 64MB
        cold_tier_path: "data/cold/",
        flush_interval: Duration::from_millis(100),
        backpressure_threshold: 0.8,                  // 80% 时触发背压
    },
    ..Default::default()
};

4. 错误处理增强

系统化梳理了全部 crate 的错误处理路径,修复了 12 个错误处理缺陷,包括未处理的 panic、静默忽略的错误与不当的错误传播。

错误处理改进

缺陷类型数量影响修复方式
未处理 panic3进程崩溃替换为 Result
静默忽略错误5数据丢失显式处理或传播
错误信息丢失4调试困难保留错误链
资源未释放8资源泄漏RAII + Drop

优雅降级机制

use eneros_core::resilience::{CircuitBreaker, FallbackPolicy};

let breaker = CircuitBreaker::new()
    .failure_threshold(5)                            // 5 次失败后熔断
    .reset_timeout(Duration::from_secs(30))          // 30 秒后尝试恢复
    .fallback(FallbackPolicy::UseLastKnownGood);     // 降级到最近可用值

match breaker.call(|| async {
    ctx.syscall(SolvePowerFlow { /* ... */ }).await
}).await {
    Ok(result) => { /* 正常结果 */ }
    Err(CircuitBreakerError::Open) => {
        // 熔断状态,使用降级值
        let fallback = ctx.cache.get_last_powerflow().await?;
        log::warn!("潮流计算熔断,使用缓存值");
    }
}

背压机制

use eneros_core::resilience::{Backpressure, BackpressureConfig};

let bp = Backpressure::new(BackpressureConfig {
    high_watermark: 0.8,        // 80% 时开始背压
    low_watermark: 0.5,         // 50% 时停止背压
    queue_capacity: 10000,
});

// 写入时检查背压
if bp.is_pressure_high() {
    // 返回背压信号,上游应减速
    return Err(BackpressureError::SlowDown);
}

bp.increment();
let result = do_work().await;
bp.decrement();

改进优化

Panic 捕获与恢复

所有 Agent 的执行入口增加 panic 捕获,防止单个 Agent 的 panic 导致整个运行时崩溃。panic 被捕获后记录完整调用栈,并触发 Agent 重启。

use eneros_agent::runtime::PanicGuard;

let guard = PanicGuard::new("dispatch-agent");
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    agent.run(ctx)
}));

match result {
    Ok(Ok(())) => { /* 正常完成 */ }
    Ok(Err(e)) => { /* Agent 返回错误 */ }
    Err(panic) => {
        let backtrace = guard.capture_backtrace(panic);
        log::error!("Agent panic: {}", backtrace);
        runtime::restart_agent("dispatch-agent").await?;
    }
}

资源限额

每个 Agent 与插件增加资源限额,防止资源耗尽影响系统稳定性。

资源默认限额超限行为
内存512 MBOOM 告警 + 重启
CPU4 核限流
文件描述符1024拒绝新 FD
网络连接256拒绝新连接
磁盘写入1 GB/h限流

优雅关闭

系统关闭时按依赖顺序逐级优雅退出,确保所有在途请求完成、缓冲区落盘与状态持久化。

use eneros_os::shutdown::{ShutdownManager, ShutdownOrder};

let manager = ShutdownManager::new()
    .timeout(Duration::from_secs(30))
    .order(ShutdownOrder::Dependency)
    .step("agents", |ctx| async { /* 停止所有 Agent */ })
    .step("api", |ctx| async { /* 关闭 API 网关 */ })
    .step("timeseries", |ctx| async { /* flush 时序数据 */ })
    .step("topology", |ctx| async { /* 持久化拓扑 */ })
    .step("kernel", |ctx| async { /* 内核清理 */ });

manager.shutdown().await?;

Bug 修复

  • BG-701:拓扑快照在并发写入时引用计数错误,已修复为原子操作
  • BG-705:Agent 上下文缓存无上限导致内存无限增长,已引入 LRU
  • BG-709:时序压缩缓冲区在写入速度超过落盘速度时无限增长,已引入背压
  • BG-713:约束引擎的历史快照未清理,已限制最大深度
  • BG-717:审计日志缓冲区未定期 flush,已改为定时落盘
  • BG-721:Agent 记忆向量无限累积,已引入分层压缩
  • BG-725:DAG 编排节点缓存未清理,已执行后清理
  • BG-729:panic 在 Agent 中未被捕获,已增加 PanicGuard
  • BG-733:文件描述符在重连时泄漏,已修复 RAII 封装
  • BG-737:优雅关闭时在途请求被丢弃,已增加 drain 期

破坏性变更

BC-251:AgentRuntime 新增资源限额配置

AgentRuntime::new 的配置参数新增 resource_limits 字段,需为现有代码补充该字段。

// v0.45.0(旧)
let runtime = AgentRuntime::new(RuntimeConfig::default());

// v0.46.0(新)
let runtime = AgentRuntime::new(RuntimeConfig {
    resource_limits: ResourceLimits::default(),
    ..Default::default()
});

BC-252:TsdbConfig 的 flush_policy 字段变更

flush_policy 从简单的 FlushInterval 改为 FlushPolicy 枚举,支持分级落盘。

依赖升级

依赖旧版本新版本说明
rustc1.751.76panic hook 增强
jemallocator0.50.5.4内存分配器
mimalloc0.10.1.39备选分配器
tracing0.1.400.1.40无变化

升级指南

从 v0.45.0 升级

rustup default 1.76.0
cargo update
cargo test --workspace

处理破坏性变更:

// 补充资源限额配置
let runtime = AgentRuntime::new(RuntimeConfig {
    resource_limits: ResourceLimits {
        max_memory_mb: 512,
        max_cpu_cores: 4,
        max_file_descriptors: 1024,
    },
    ..Default::default()
});

运行压力测试验证稳定性:

eneros-cli stress run --scenario full-load --duration 7h
eneros-cli stress report

相关文档