SpringBoot + 任务执行资源隔离 + CPU/内存配额:关键任务独占资源,避免被其他任务拖垮

1. 问题背景:为什么需要任务执行资源隔离?

在现代应用中,我们经常需要处理各种类型的任务,有些是关键任务(如订单处理、支付交易),有些是非关键任务(如日志分析、数据导出)。如果所有任务都在同一个线程池和资源环境中执行,可能会导致以下问题:

  • 资源竞争:非关键任务占用大量CPU和内存资源,导致关键任务执行缓慢
  • 系统不稳定:某个任务出现内存泄漏或CPU占用过高,可能影响整个应用的稳定性
  • 难以调优:无法针对不同类型的任务设置不同的资源限制和执行策略
  • 故障隔离:一个任务的故障可能会影响其他任务的执行

因此,实现任务执行资源隔离,为不同类型的任务分配独立的资源配额,成为保证系统稳定性和关键任务执行质量的重要手段。

2. 核心概念:任务执行资源隔离的原理

2.1 资源隔离的基本概念

资源隔离是指将系统资源(如CPU、内存、网络等)划分为不同的资源池,不同类型的任务只能使用分配给它们的资源池,从而避免资源竞争和相互影响。

2.2 资源隔离的实现方式

在Spring Boot应用中,实现任务执行资源隔离的主要方式有:

  1. 线程池隔离:为不同类型的任务创建独立的线程池,控制每个线程池的线程数量和队列大小
  2. 进程隔离:将不同类型的任务部署在不同的进程中,完全隔离资源
  3. 容器隔离:使用Docker容器等技术,为不同类型的任务创建独立的容器,隔离CPU、内存等资源
  4. 资源配额:为不同类型的任务设置CPU和内存配额,限制它们的资源使用

2.3 CPU/内存配额的实现原理

CPU/内存配额是指为任务或进程设置的CPU和内存使用上限,超过上限后系统会限制其资源使用。在Java应用中,可以通过以下方式实现:

  1. JVM参数:通过JVM参数设置堆内存大小、线程栈大小等
  2. 操作系统限制:使用操作系统的资源限制机制,如Linux的cgroups
  3. 应用级限制:在应用层面实现资源使用监控和限制

3. 实现方案:Spring Boot任务执行资源隔离

3.1 线程池隔离实现

在Spring Boot中,我们可以使用ThreadPoolTaskExecutorThreadPoolExecutor为不同类型的任务创建独立的线程池。

配置不同类型的线程池

@Configuration
public class TaskExecutorConfig {

    // 关键任务线程池
    @Bean("criticalTaskExecutor")
    public TaskExecutor criticalTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("critical-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    // 非关键任务线程池
    @Bean("nonCriticalTaskExecutor")
    public TaskExecutor nonCriticalTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(50);
        executor.setThreadNamePrefix("non-critical-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

}

使用不同的线程池执行任务

@Service
public class TaskService {

    @Autowired
    @Qualifier("criticalTaskExecutor")
    private TaskExecutor criticalTaskExecutor;

    @Autowired
    @Qualifier("nonCriticalTaskExecutor")
    private TaskExecutor nonCriticalTaskExecutor;

    // 执行关键任务
    public void executeCriticalTask(Runnable task) {
        criticalTaskExecutor.execute(task);
    }

    // 执行非关键任务
    public void executeNonCriticalTask(Runnable task) {
        nonCriticalTaskExecutor.execute(task);
    }

}

3.2 资源配额实现

在Spring Boot中,我们可以使用Java的ThreadMXBeanRuntime类监控和限制任务的资源使用。

CPU使用监控

public class CpuMonitor {

    private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

    // 监控线程CPU使用情况
    public static double getThreadCpuUsage(long threadId) {
        if (threadMXBean.isThreadCpuTimeSupported()) {
            long cpuTime = threadMXBean.getThreadCpuTime(threadId);
            long userTime = threadMXBean.getThreadUserTime(threadId);
            return (cpuTime - userTime) / 1000000.0; // 转换为毫秒
        }
        return 0.0;
    }

    // 监控进程CPU使用情况
    public static double getProcessCpuUsage() {
        if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
            long cpuTime = threadMXBean.getCurrentThreadCpuTime();
            long userTime = threadMXBean.getCurrentThreadUserTime();
            return (cpuTime - userTime) / 1000000.0; // 转换为毫秒
        }
        return 0.0;
    }

}

内存使用监控

public class MemoryMonitor {

    private static final Runtime runtime = Runtime.getRuntime();

    // 获取已用内存
    public static long getUsedMemory() {
        return runtime.totalMemory() - runtime.freeMemory();
    }

    // 获取最大内存
    public static long getMaxMemory() {
        return runtime.maxMemory();
    }

    // 获取内存使用百分比
    public static double getMemoryUsagePercentage() {
        return (double) getUsedMemory() / getMaxMemory() * 100;
    }

}

资源配额控制

public class ResourceQuotaManager {

    // 检查CPU使用是否超过配额
    public static boolean isCpuUsageExceeded(double cpuUsage, double quota) {
        return cpuUsage > quota;
    }

    // 检查内存使用是否超过配额
    public static boolean isMemoryUsageExceeded(double memoryUsage, double quota) {
        return memoryUsage > quota;
    }

    // 限制任务执行时间
    public static void executeWithTimeout(Runnable task, long timeoutMs) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<?> future = executor.submit(task);
        try {
            future.get(timeoutMs, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            future.cancel(true);
            throw new RuntimeException("任务执行超时", e);
        } catch (Exception e) {
            throw new RuntimeException("任务执行失败", e);
        } finally {
            executor.shutdown();
        }
    }

}

3.3 任务执行隔离框架

我们可以创建一个任务执行隔离框架,为不同类型的任务提供独立的执行环境和资源配额。

任务执行器接口

public interface TaskExecutor {

    // 执行任务
    void execute(Runnable task);

    // 执行任务并返回结果
    <T> Future<T> submit(Callable<T> task);

    // 获取线程池名称
    String getName();

    // 获取资源配额
    ResourceQuota getResourceQuota();

}

资源配额类

public class ResourceQuota {

    private double cpuQuota; // CPU使用上限(百分比)
    private long memoryQuota; // 内存使用上限(字节)
    private long timeout; // 任务执行超时时间(毫秒)

    // 构造方法、getter和setter

}

任务执行器实现

public class IsolatedTaskExecutor implements TaskExecutor {

    private final String name;
    private final ExecutorService executorService;
    private final ResourceQuota resourceQuota;

    public IsolatedTaskExecutor(String name, int corePoolSize, int maxPoolSize, int queueCapacity, ResourceQuota resourceQuota) {
        this.name = name;
        this.executorService = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(queueCapacity),
                new ThreadFactoryBuilder().setNameFormat(name + "-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        this.resourceQuota = resourceQuota;
    }

    @Override
    public void execute(Runnable task) {
        executorService.execute(() -> {
            // 监控资源使用
            monitorResourceUsage(task);
        });
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return executorService.submit(() -> {
            // 监控资源使用
            return monitorResourceUsage(task);
        });
    }

    // 监控资源使用
    private void monitorResourceUsage(Runnable task) {
        long startTime = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();

        try {
            task.run();
        } finally {
            long endTime = System.currentTimeMillis();
            double cpuUsage = CpuMonitor.getThreadCpuUsage(threadId);
            long memoryUsage = MemoryMonitor.getUsedMemory();

            // 检查资源使用是否超过配额
            if (ResourceQuotaManager.isCpuUsageExceeded(cpuUsage, resourceQuota.getCpuQuota())) {
                System.out.println(name + " CPU使用超过配额: " + cpuUsage + "% > " + resourceQuota.getCpuQuota() + "%");
            }

            if (ResourceQuotaManager.isMemoryUsageExceeded(memoryUsage, resourceQuota.getMemoryQuota())) {
                System.out.println(name + " 内存使用超过配额: " + memoryUsage + "B > " + resourceQuota.getMemoryQuota() + "B");
            }

            // 检查任务执行时间是否超过超时时间
            if (endTime - startTime > resourceQuota.getTimeout()) {
                System.out.println(name + " 任务执行超时: " + (endTime - startTime) + "ms > " + resourceQuota.getTimeout() + "ms");
            }
        }
    }

    // 监控资源使用(带返回值)
    private <T> T monitorResourceUsage(Callable<T> task) throws Exception {
        long startTime = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();

        try {
            return task.call();
        } finally {
            long endTime = System.currentTimeMillis();
            double cpuUsage = CpuMonitor.getThreadCpuUsage(threadId);
            long memoryUsage = MemoryMonitor.getUsedMemory();

            // 检查资源使用是否超过配额
            if (ResourceQuotaManager.isCpuUsageExceeded(cpuUsage, resourceQuota.getCpuQuota())) {
                System.out.println(name + " CPU使用超过配额: " + cpuUsage + "% > " + resourceQuota.getCpuQuota() + "%");
            }

            if (ResourceQuotaManager.isMemoryUsageExceeded(memoryUsage, resourceQuota.getMemoryQuota())) {
                System.out.println(name + " 内存使用超过配额: " + memoryUsage + "B > " + resourceQuota.getMemoryQuota() + "B");
            }

            // 检查任务执行时间是否超过超时时间
            if (endTime - startTime > resourceQuota.getTimeout()) {
                System.out.println(name + " 任务执行超时: " + (endTime - startTime) + "ms > " + resourceQuota.getTimeout() + "ms");
            }
        }
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public ResourceQuota getResourceQuota() {
        return resourceQuota;
    }

    // 关闭线程池
    public void shutdown() {
        executorService.shutdown();
    }

}

任务执行隔离配置

@Configuration
public class TaskIsolationConfig {

    // 关键任务执行器
    @Bean("criticalTaskExecutor")
    public TaskExecutor criticalTaskExecutor() {
        ResourceQuota resourceQuota = new ResourceQuota();
        resourceQuota.setCpuQuota(50.0); // CPU使用上限50%
        resourceQuota.setMemoryQuota(1024 * 1024 * 1024); // 内存使用上限1GB
        resourceQuota.setTimeout(60000); // 任务执行超时时间60秒

        return new IsolatedTaskExecutor(
                "critical-task-executor",
                10,
                20,
                100,
                resourceQuota
        );
    }

    // 非关键任务执行器
    @Bean("nonCriticalTaskExecutor")
    public TaskExecutor nonCriticalTaskExecutor() {
        ResourceQuota resourceQuota = new ResourceQuota();
        resourceQuota.setCpuQuota(30.0); // CPU使用上限30%
        resourceQuota.setMemoryQuota(512 * 1024 * 1024); // 内存使用上限512MB
        resourceQuota.setTimeout(300000); // 任务执行超时时间5分钟

        return new IsolatedTaskExecutor(
                "non-critical-task-executor",
                5,
                10,
                50,
                resourceQuota
        );
    }

}

4. 最佳实践:任务执行资源隔离的设计原则

4.1 任务分类

在设计任务执行资源隔离时,首先需要对任务进行分类,根据任务的重要性、执行时间、资源需求等因素,将任务分为不同的类别。

任务分类建议

  • 关键任务:如订单处理、支付交易、用户认证等,需要优先保证执行质量和响应速度
  • 重要任务:如数据同步、消息处理等,需要保证执行质量,但对响应速度要求较低
  • 普通任务:如日志处理、数据统计等,对执行质量和响应速度要求都较低
  • 后台任务:如系统维护、数据清理等,对执行质量和响应速度要求最低

4.2 资源分配策略

根据任务的分类,为不同类型的任务分配不同的资源配额和执行策略。

资源分配建议

  • 关键任务:分配较多的CPU和内存资源,设置较短的执行超时时间,使用独立的线程池
  • 重要任务:分配适中的CPU和内存资源,设置中等的执行超时时间,使用独立的线程池
  • 普通任务:分配较少的CPU和内存资源,设置较长的执行超时时间,使用共享的线程池
  • 后台任务:分配最少的CPU和内存资源,设置最长的执行超时时间,使用共享的线程池

4.3 监控和告警

为了及时发现和处理资源使用异常,需要对任务的资源使用情况进行监控和告警。

监控和告警建议

  • 实时监控:实时监控任务的CPU和内存使用情况
  • 阈值告警:当资源使用超过阈值时,触发告警
  • 历史分析:分析历史资源使用数据,优化资源分配策略
  • 自动调优:根据历史数据,自动调整资源配额和执行策略

4.4 故障处理

为了保证系统的稳定性,需要对任务执行过程中的故障进行处理。

故障处理建议

  • 任务隔离:一个任务的故障不会影响其他任务的执行
  • 故障重试:对于临时性故障,进行自动重试
  • 故障降级:当系统资源不足时,降级非关键任务的执行质量
  • 故障恢复:当系统资源恢复时,恢复任务的执行质量

5. 代码示例:Spring Boot任务执行资源隔离

5.1 项目结构

task-isolation-demo/
├── src/
│   ├── main/
│   │   ├── java/com/example/task/
│   │   │   ├── config/             # 配置类
│   │   │   ├── executor/           # 执行器
│   │   │   ├── monitor/            # 监控工具
│   │   │   ├── quota/              # 资源配额
│   │   │   ├── service/            # 服务类
│   │   │   ├── controller/         # 控制器
│   │   │   └── TaskIsolationDemoApplication.java  # 应用入口
│   │   └── resources/             # 配置文件
│   └── test/                      # 测试代码
└── pom.xml                        # Maven 依赖

5.2 核心代码

资源配额类

package com.example.task.quota;

import lombok.Data;

@Data
public class ResourceQuota {

    private double cpuQuota; // CPU使用上限(百分比)
    private long memoryQuota; // 内存使用上限(字节)
    private long timeout; // 任务执行超时时间(毫秒)

    public ResourceQuota() {
        this.cpuQuota = 100.0;
        this.memoryQuota = Long.MAX_VALUE;
        this.timeout = Long.MAX_VALUE;
    }

}

CPU监控工具

package com.example.task.monitor;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class CpuMonitor {

    private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

    // 监控线程CPU使用情况
    public static double getThreadCpuUsage(long threadId) {
        if (threadMXBean.isThreadCpuTimeSupported()) {
            long cpuTime = threadMXBean.getThreadCpuTime(threadId);
            long userTime = threadMXBean.getThreadUserTime(threadId);
            return (cpuTime - userTime) / 1000000.0; // 转换为毫秒
        }
        return 0.0;
    }

    // 监控进程CPU使用情况
    public static double getProcessCpuUsage() {
        if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
            long cpuTime = threadMXBean.getCurrentThreadCpuTime();
            long userTime = threadMXBean.getCurrentThreadUserTime();
            return (cpuTime - userTime) / 1000000.0; // 转换为毫秒
        }
        return 0.0;
    }

}

内存监控工具

package com.example.task.monitor;

public class MemoryMonitor {

    private static final Runtime runtime = Runtime.getRuntime();

    // 获取已用内存
    public static long getUsedMemory() {
        return runtime.totalMemory() - runtime.freeMemory();
    }

    // 获取最大内存
    public static long getMaxMemory() {
        return runtime.maxMemory();
    }

    // 获取内存使用百分比
    public static double getMemoryUsagePercentage() {
        return (double) getUsedMemory() / getMaxMemory() * 100;
    }

}

资源配额管理

package com.example.task.quota;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ResourceQuotaManager {

    // 检查CPU使用是否超过配额
    public static boolean isCpuUsageExceeded(double cpuUsage, double quota) {
        return cpuUsage > quota;
    }

    // 检查内存使用是否超过配额
    public static boolean isMemoryUsageExceeded(double memoryUsage, double quota) {
        return memoryUsage > quota;
    }

    // 限制任务执行时间
    public static void executeWithTimeout(Runnable task, long timeoutMs) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<?> future = executor.submit(task);
        try {
            future.get(timeoutMs, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            future.cancel(true);
            throw new RuntimeException("任务执行超时", e);
        } finally {
            executor.shutdown();
        }
    }

}

任务执行器接口

package com.example.task.executor;

import com.example.task.quota.ResourceQuota;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

public interface TaskExecutor {

    // 执行任务
    void execute(Runnable task);

    // 执行任务并返回结果
    <T> Future<T> submit(Callable<T> task);

    // 获取线程池名称
    String getName();

    // 获取资源配额
    ResourceQuota getResourceQuota();

}

隔离任务执行器

package com.example.task.executor;

import com.example.task.monitor.CpuMonitor;
import com.example.task.monitor.MemoryMonitor;
import com.example.task.quota.ResourceQuota;
import com.example.task.quota.ResourceQuotaManager;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;

public class IsolatedTaskExecutor implements TaskExecutor {

    private final String name;
    private final ExecutorService executorService;
    private final ResourceQuota resourceQuota;

    public IsolatedTaskExecutor(String name, int corePoolSize, int maxPoolSize, int queueCapacity, ResourceQuota resourceQuota) {
        this.name = name;
        this.executorService = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(queueCapacity),
                new ThreadFactoryBuilder().setNameFormat(name + "-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        this.resourceQuota = resourceQuota;
    }

    @Override
    public void execute(Runnable task) {
        executorService.execute(() -> {
            // 监控资源使用
            monitorResourceUsage(task);
        });
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return executorService.submit(() -> {
            // 监控资源使用
            return monitorResourceUsage(task);
        });
    }

    // 监控资源使用
    private void monitorResourceUsage(Runnable task) {
        long startTime = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();

        try {
            task.run();
        } finally {
            long endTime = System.currentTimeMillis();
            double cpuUsage = CpuMonitor.getThreadCpuUsage(threadId);
            long memoryUsage = MemoryMonitor.getUsedMemory();

            // 检查资源使用是否超过配额
            if (ResourceQuotaManager.isCpuUsageExceeded(cpuUsage, resourceQuota.getCpuQuota())) {
                System.out.println(name + " CPU使用超过配额: " + cpuUsage + "% > " + resourceQuota.getCpuQuota() + "%");
            }

            if (ResourceQuotaManager.isMemoryUsageExceeded(memoryUsage, resourceQuota.getMemoryQuota())) {
                System.out.println(name + " 内存使用超过配额: " + memoryUsage + "B > " + resourceQuota.getMemoryQuota() + "B");
            }

            // 检查任务执行时间是否超过超时时间
            if (endTime - startTime > resourceQuota.getTimeout()) {
                System.out.println(name + " 任务执行超时: " + (endTime - startTime) + "ms > " + resourceQuota.getTimeout() + "ms");
            }
        }
    }

    // 监控资源使用(带返回值)
    private <T> T monitorResourceUsage(Callable<T> task) throws Exception {
        long startTime = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();

        try {
            return task.call();
        } finally {
            long endTime = System.currentTimeMillis();
            double cpuUsage = CpuMonitor.getThreadCpuUsage(threadId);
            long memoryUsage = MemoryMonitor.getUsedMemory();

            // 检查资源使用是否超过配额
            if (ResourceQuotaManager.isCpuUsageExceeded(cpuUsage, resourceQuota.getCpuQuota())) {
                System.out.println(name + " CPU使用超过配额: " + cpuUsage + "% > " + resourceQuota.getCpuQuota() + "%");
            }

            if (ResourceQuotaManager.isMemoryUsageExceeded(memoryUsage, resourceQuota.getMemoryQuota())) {
                System.out.println(name + " 内存使用超过配额: " + memoryUsage + "B > " + resourceQuota.getMemoryQuota() + "B");
            }

            // 检查任务执行时间是否超过超时时间
            if (endTime - startTime > resourceQuota.getTimeout()) {
                System.out.println(name + " 任务执行超时: " + (endTime - startTime) + "ms > " + resourceQuota.getTimeout() + "ms");
            }
        }
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public ResourceQuota getResourceQuota() {
        return resourceQuota;
    }

    // 关闭线程池
    public void shutdown() {
        executorService.shutdown();
    }

}

任务执行隔离配置

package com.example.task.config;

import com.example.task.executor.IsolatedTaskExecutor;
import com.example.task.executor.TaskExecutor;
import com.example.task.quota.ResourceQuota;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TaskIsolationConfig {

    // 关键任务执行器
    @Bean("criticalTaskExecutor")
    public TaskExecutor criticalTaskExecutor() {
        ResourceQuota resourceQuota = new ResourceQuota();
        resourceQuota.setCpuQuota(50.0); // CPU使用上限50%
        resourceQuota.setMemoryQuota(1024 * 1024 * 1024); // 内存使用上限1GB
        resourceQuota.setTimeout(60000); // 任务执行超时时间60秒

        return new IsolatedTaskExecutor(
                "critical-task-executor",
                10,
                20,
                100,
                resourceQuota
        );
    }

    // 非关键任务执行器
    @Bean("nonCriticalTaskExecutor")
    public TaskExecutor nonCriticalTaskExecutor() {
        ResourceQuota resourceQuota = new ResourceQuota();
        resourceQuota.setCpuQuota(30.0); // CPU使用上限30%
        resourceQuota.setMemoryQuota(512 * 1024 * 1024); // 内存使用上限512MB
        resourceQuota.setTimeout(300000); // 任务执行超时时间5分钟

        return new IsolatedTaskExecutor(
                "non-critical-task-executor",
                5,
                10,
                50,
                resourceQuota
        );
    }

}

任务服务

package com.example.task.service;

import com.example.task.executor.TaskExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class TaskService {

    @Autowired
    @Qualifier("criticalTaskExecutor")
    private TaskExecutor criticalTaskExecutor;

    @Autowired
    @Qualifier("nonCriticalTaskExecutor")
    private TaskExecutor nonCriticalTaskExecutor;

    // 执行关键任务
    public void executeCriticalTask(Runnable task) {
        criticalTaskExecutor.execute(task);
    }

    // 执行非关键任务
    public void executeNonCriticalTask(Runnable task) {
        nonCriticalTaskExecutor.execute(task);
    }

}

测试控制器

package com.example.task.controller;

import com.example.task.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private TaskService taskService;

    // 测试关键任务
    @GetMapping("/critical")
    public String testCriticalTask() {
        taskService.executeCriticalTask(() -> {
            System.out.println("执行关键任务");
            // 模拟任务执行
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return "关键任务已提交";
    }

    // 测试非关键任务
    @GetMapping("/non-critical")
    public String testNonCriticalTask() {
        taskService.executeNonCriticalTask(() -> {
            System.out.println("执行非关键任务");
            // 模拟任务执行
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return "非关键任务已提交";
    }

}

5.3 配置文件

application.yml

spring:
  application:
    name: task-isolation-demo

# 任务执行资源隔离配置
 task:
   isolation:
     critical:
       cpu-quota: 50.0
       memory-quota: 1024MB
       timeout: 60s
     non-critical:
       cpu-quota: 30.0
       memory-quota: 512MB
       timeout: 300s

# 服务器配置
server:
  port: 8080

5.4 测试场景

测试关键任务

curl http://localhost:8080/test/critical

测试非关键任务

curl http://localhost:8080/test/non-critical

测试资源使用监控

  • 执行关键任务,观察CPU和内存使用情况
  • 执行非关键任务,观察CPU和内存使用情况
  • 同时执行多个任务,观察资源隔离效果

6. 总结

通过不断优化和扩展,我们可以构建一个更加智能、高效、可靠的任务执行资源隔离系统,为应用程序的稳定运行提供有力保障。

更多技术文章,欢迎关注公众号:服务端技术精选


标题:SpringBoot + 任务执行资源隔离 + CPU/内存配额:关键任务独占资源,避免被其他任务拖垮
作者:jiangyi
地址:http://jiangyi.space/articles/2026/04/13/1775892313337.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消