java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot线程池的订单创建并行化实践

SpringBoot基于线程池的订单创建并行化实践过程

作者:kkkkkkkkl24

文章介绍了电商系统订单创建接口的并行处理方案,通过分析业务流程、选择合适的线程池和技术,解决了高并发场景下的性能问题

一、背景

1.1 业务背景

以电商系统「订单创建」接口为例

一个用户下单请求,往往需要完成多个业务步骤:

1.2 问题描述

传统实现方式:串行执行

在高并发场景下:

1.3 技术挑战

二、业务场景分析与并行拆分

2.1 订单创建流程拆解

步骤是否存在依赖是否可并行
校验库存
校验用户
计算价格
锁库存依赖库存校验
创建订单依赖前置结果

2.2 并行化设计思路

三、技术选型与整体设计

3.1 为什么不直接 new Thread?

3.2 为什么选择线程池 + CompletableFuture?

3.3 在 Spring Boot 中的正确姿势

四、线程池设计与配置(Core)

4.1 线程池配置代码

@Configuration
public class OrderThreadPoolConfig {

    @Bean("orderExecutor")
    public ThreadPoolTaskExecutor orderExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(16);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("order-create-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

4.2 关键参数说明

4.3 线程池定位

五、核心业务实现

5.1 校验 Service(模拟 RPC / DB)

@Service
public class OrderCheckService {

    public boolean checkStock(Long skuId) {
        sleep(100);
        return true;
    }

    public boolean checkUser(Long userId) {
        sleep(80);
        return true;
    }

    public int calcPrice(Long skuId) {
        sleep(120);
        return 99;
    }

    private void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

5.2 订单创建核心逻辑

@Service
public class OrderService {

    @Resource(name = "orderExecutor")
    private Executor orderExecutor;

    @Autowired
    private OrderCheckService orderCheckService;

    public String createOrder(Long userId, Long skuId) throws Exception {

        long start = System.currentTimeMillis();

        CompletableFuture<Boolean> stockFuture =
                CompletableFuture.supplyAsync(
                        () -> orderCheckService.checkStock(skuId),
                        orderExecutor);

        CompletableFuture<Boolean> userFuture =
                CompletableFuture.supplyAsync(
                        () -> orderCheckService.checkUser(userId),
                        orderExecutor);

        CompletableFuture<Integer> priceFuture =
                CompletableFuture.supplyAsync(
                        () -> orderCheckService.calcPrice(skuId),
                        orderExecutor);

        CompletableFuture.allOf(
                stockFuture, userFuture, priceFuture).join();

        if (!stockFuture.get()) {
            throw new RuntimeException("库存不足");
        }

        int price = priceFuture.get();

        lockStock(skuId);
        saveOrder(userId, skuId, price);

        return "success, cost=" +
                (System.currentTimeMillis() - start) + "ms";
    }

    private void lockStock(Long skuId) {
        sleep(50);
    }

    private void saveOrder(Long userId, Long skuId, int price) {
        sleep(80);
    }

    private void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

5.3 Controller

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/create")
    public String createOrder(
            @RequestParam Long userId,
            @RequestParam Long skuId) throws Exception {
        return orderService.createOrder(userId, skuId);
    }
}

六、JMeter 压测与结果分析

6.1 压测配置说明

6.2 压测现象

系统启动初期:

持续压测后:

6.3 原因分析

6.4 工程结论

线程池优化的是系统吞吐与稳定性,而不是在无限并发下保持恒定响应时间。

七、问题思考

7.1 为什么不用 @Async?

7.2 为什么不用 parallelStream?

7.3 线程池并非万能

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文