山大软院创新实训易学探索助手---个人报告(五)

测试和问题描述

本周我对系统进行了多项测试,其中包括在极端条件下的系统性能测试,发现了一个潜在风险并进行了修复,具体问题及修复过程如下。

在开发系统时,我设计了一个TaskService 服务,用于管理异步任务的创建、查询和状态更新。
task相关核心代码如下:

@Service
public class TaskService {
    private final Map<String, Task> tasks = new ConcurrentHashMap<>();

    public String createTask() {
        String taskId = "TASK-" + System.currentTimeMillis();
        tasks.put(taskId, new Task(taskId));
        return taskId;
    }

    // 其他方法:getTask、updateResult、deleteTask
}

潜在风险

  • 内存泄漏:所有任务对象(Task)均存储在 ConcurrentHashMap 中,若不主动删除已完成的任务,随着时间推移,内存占用将持续增长。
  • OOM 风险:在高频任务创建场景下(如每秒生成数百个任务),堆内存可能快速耗尽,导致 OutOfMemoryError

一、内存泄漏复现与测试

测试代码

为了验证内存泄漏问题,编写了一个模拟无限创建任务的测试程序:

public static void main(String[] args) {
    TaskService taskService = new TaskService();
    while (true) {
        taskService.createTask(); // 持续创建任务,不删除
    }
}

测试过程

  1. 启动测试程序:运行上述 main 方法,持续创建任务。
  2. 监控工具:使用 JConsole 连接 JVM 进程,观察内存变化。

测试结果

  • 内存趋势:堆内存使用量随时间不断增长(如下图所示)。
  • 最终结果:约 20 分钟后抛出 java.lang.OutOfMemoryError: Java heap space

二、性能优化方案

1. 问题根因分析

  • 数据生命周期失控:任务完成后未及时清理,ConcurrentHashMap 长期持有对象引用。
  • 缺乏自动回收机制:依赖业务代码显式调用 deleteTask,易遗漏。

2. 优化方案:定时清理已完成任务

通过 Spring Boot 的定时任务功能,定期清理所有状态为 DONE 的任务。

代码实现

import org.springframework.scheduling.annotation.Scheduled;

@Service
public class TaskService {
    private final Map<String, Task> tasks = new ConcurrentHashMap<>();

    // 每5分钟清理一次已完成的任务
    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void autoCleanTasks() {
        int initialSize = tasks.size();
        tasks.entrySet().removeIf(entry -> 
            Task.Status.DONE.equals(entry.getValue().getStatus())
        );
        System.out.printf("已清理任务:%d → %d(删除 %d 个)%n", 
            initialSize, tasks.size(), initialSize - tasks.size());
    }
}

关键配置

  • 在 Spring Boot 主类添加 @EnableScheduling 注解:
    @SpringBootApplication
    @EnableScheduling // 启用定时任务
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    

3. 方案优势

  • 自动化:无需业务代码主动触发,降低人为遗漏风险。
  • 可控性:通过 fixedRate 参数灵活调整清理频率(如生产环境可设置为 1 小时)。
  • 低开销ConcurrentHashMap 的遍历操作线程安全且高效。

三、优化效果验证

测试场景

  • 模拟正常业务:持续创建任务,并为每个任务随机设置完成状态。
  • 监控指标:堆内存使用量、GC 频率、任务清理日志。

测试结果

  • 内存趋势:堆内存周期性波动,无持续增长。
  • 日志输出
    已清理任务:1520 → 320(删除 1200 个)
    已清理任务:1800 → 250(删除 1550 个)
    
  • OOM 问题解决:长时间运行(24 小时)未发生内存溢出。

四、总结

关键结论

  1. 问题定位:未清理的已完成任务导致内存泄漏是 OOM 的直接原因。
  2. 优化效果:定时清理机制使内存使用从持续增长变为周期性释放,彻底解决溢出风险。
  3. 方法论:内存管理需结合业务场景设计数据生命周期,并借助自动化机制保障。

通过本次实践,我们不仅解决了一个典型的内存泄漏问题,更强化了对资源生命周期管理的意识。在分布式系统和高并发场景下,类似问题需通过 代码设计 + 监控告警 + 自动化回收 的组合拳来系统性规避。相信我在本次发现问题后能够积累相关经验,在之后开发项目的过程中注重内存的相关问题。

posted @ 2025-05-01 12:20  htekye  阅读(49)  评论(0)    收藏  举报