企业级CompletableFuture并行化完整方案,接口从10s到100ms

一、企业级 CompletableFuture 核心使用原则(先定规范,再谈场景)

在进入具体场景前,先明确企业落地时必须遵守的核心原则(这是"合理使用"的前提):

原则 企业级要求 落地说明
线程池隔离 不同业务域用独立线程池 订单业务、用户业务、报表业务各用一个线程池,避免"一个业务打满线程池影响全系统"
超时必加 所有异步调用必须设置超时 分布式场景下,超时时间建议 200~500ms(根据依赖服务的SLA调整)
异常兜底 无异常吞掉,必须返回降级结果 比如商品服务调用失败,返回"商品信息暂未获取"而非空指针
并行度可控 批量场景限制并行数 比如批量查询100个商品,控制并行数为10,避免打垮依赖服务
仅用查询场景 只用于无状态、读操作、非事务场景 写操作/事务场景(如支付、转账)绝对不用,避免数据不一致

二、企业高频核心业务场景(附完整方案+代码)

以下是企业中 90% 以上会用到 CompletableFuture 的场景,按"场景描述→方案设计→完整代码→测试验证"组织,代码可直接复制到 Spring Cloud 项目中使用。

场景1:电商订单详情页(多服务并行聚合)

场景描述

电商平台的订单详情页是企业最典型的场景:用户点击订单后,需要查询订单基础信息、用户信息、商品信息、物流信息、优惠券信息 5个维度的数据,若串行调用,响应时间=各服务耗时之和(比如每个服务200ms,总计1000ms);用 CompletableFuture 并行调用,响应时间=最长单个服务耗时(200ms),提升5倍效率。

方案设计

  1. 线程池:创建"订单业务专用线程池",隔离其他业务;
  2. 异步调用:5个维度的数据并行调用,每个调用加超时+异常兜底;
  3. 结果聚合:等待所有异步任务完成后,组装最终的订单详情;
  4. 监控:线程池关键指标(活跃数、队列长度)接入Prometheus(企业级必备)。

完整代码

步骤1:依赖配置(pom.xml)
xml 复制代码
<!-- 核心依赖(Spring Cloud 基础) -->
<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- OpenFeign(微服务调用) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!-- Lombok(简化代码) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- 测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- 线程池监控(企业级必备) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>
步骤2:线程池配置(订单业务专用)
scss 复制代码
@Configuration
@Slf4j
public class OrderThreadPoolConfig {
    /**
     * 订单业务异步线程池(企业级配置:隔离+有界队列+友好命名+合理拒绝策略)
     */
    @Bean("orderAsyncExecutor")
    public Executor orderAsyncExecutor() {
        // 企业级参数计算:核心线程数=CPU核心数*2,最大=CPU*4,队列大小=1000(避免OOM)
        int core = Runtime.getRuntime().availableProcessors() * 2;
        int max = Runtime.getRuntime().availableProcessors() * 4;
        // 线程命名:格式为"业务名-线程池-序号",便于日志排查
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("order-async-pool-%d")
                .setUncaughtExceptionHandler((t, e) -> log.error("订单线程池异常:线程{}", t.getName(), e))
                .build();
        // 有界队列:企业级必须用有界,避免无界队列导致OOM
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(1000);
        // 拒绝策略:CallerRunsPolicy(调用线程执行),避免高并发下任务丢失
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                core, max, 60L, TimeUnit.SECONDS,
                queue, threadFactory, handler
        );
        // 企业级:设置线程池关闭时等待任务完成
        executor.allowCoreThreadTimeOut(true);
        return executor;
    }
}
步骤3:Feign客户端(模拟微服务调用)
less 复制代码
// 1. 订单基础信息服务(本地服务,也可Feign)
@FeignClient(name = "order-base-service", fallback = OrderBaseFallback.class)
public interface OrderBaseFeignClient {
    @GetMapping("/order/base/{orderId}")
    OrderBaseDTO getOrderBase(@PathVariable("orderId") Long orderId);
}

// 2. 用户信息服务
@FeignClient(name = "user-service", fallback = UserFallback.class)
public interface UserFeignClient {
    @GetMapping("/user/{userId}")
    UserDTO getUserById(@PathVariable("userId") Long userId);
}

// 3. 商品信息服务
@FeignClient(name = "product-service", fallback = ProductFallback.class)
public interface ProductFeignClient {
    @GetMapping("/product/{productId}")
    ProductDTO getProductById(@PathVariable("productId") Long productId);
}

// 4. 物流信息服务
@FeignClient(name = "logistics-service", fallback = LogisticsFallback.class)
public interface LogisticsFeignClient {
    @GetMapping("/logistics/order/{orderId}")
    LogisticsDTO getLogisticsByOrderId(@PathVariable("orderId") Long orderId);
}

// 5. 优惠券服务
@FeignClient(name = "coupon-service", fallback = CouponFallback.class)
public interface CouponFeignClient {
    @GetMapping("/coupon/order/{orderId}")
    List<CouponDTO> getCouponsByOrderId(@PathVariable("orderId") Long orderId);
}

// 降级实现(以订单基础服务为例,其他类似)
@Component
public class OrderBaseFallback implements OrderBaseFeignClient {
    @Override
    public OrderBaseDTO getOrderBase(Long orderId) {
        // 降级结果:返回基础默认值,避免前端空指针
        return OrderBaseDTO.builder()
                .orderId(orderId)
                .orderStatus("暂未获取")
                .createTime(LocalDateTime.now())
                .build();
    }
}
步骤4:DTO定义(企业级规范:清晰命名+Builder模式)
kotlin 复制代码
// 最终返回的订单详情DTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderDetailDTO {
    private Long orderId;          // 订单ID
    private OrderBaseDTO orderBase; // 订单基础信息
    private UserDTO user;          // 用户信息
    private ProductDTO product;    // 商品信息
    private LogisticsDTO logistics;// 物流信息
    private List<CouponDTO> coupons;// 优惠券信息
    private Long totalCost;        // 总耗时(用于测试验证)
}

// 订单基础DTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderBaseDTO {
    private Long orderId;
    private String orderStatus;
    private LocalDateTime createTime;
}

// 用户DTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
    private Long userId;
    private String userName;
    private String phone;
}

// 商品DTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductDTO {
    private Long productId;
    private String productName;
    private BigDecimal price;
}

// 物流DTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LogisticsDTO {
    private Long orderId;
    private String logisticsStatus;
    private String expressCompany;
}

// 优惠券DTO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CouponDTO {
    private Long couponId;
    private String couponName;
    private BigDecimal discount;
}
步骤5:核心业务服务(订单详情聚合)
scss 复制代码
@Service
@Slf4j
public class OrderDetailService {
    @Resource
    private OrderBaseFeignClient orderBaseFeignClient;
    @Resource
    private UserFeignClient userFeignClient;
    @Resource
    private ProductFeignClient productFeignClient;
    @Resource
    private LogisticsFeignClient logisticsFeignClient;
    @Resource
    private CouponFeignClient couponFeignClient;

    // 注入订单专用线程池
    @Resource
    @Qualifier("orderAsyncExecutor")
    private Executor orderAsyncExecutor;

    /**
     * 企业级订单详情查询核心方法
     * @param orderId 订单ID
     * @return 完整订单详情
     */
    public OrderDetailDTO getOrderDetail(Long orderId) {
        long start = System.currentTimeMillis();
        OrderDetailDTO.OrderDetailDTOBuilder builder = OrderDetailDTO.builder().orderId(orderId);

        // 1. 先查订单基础信息(必须先查,因为里面有userId/productId)
        OrderBaseDTO orderBase = orderBaseFeignClient.getOrderBase(orderId);
        builder.orderBase(orderBase);
        Long userId = 1001L; // 实际从orderBase中获取
        Long productId = 2001L; // 实际从orderBase中获取

        // 2. 异步调用用户服务(超时200ms+异常兜底)
        CompletableFuture<UserDTO> userFuture = CompletableFuture.supplyAsync(() -> {
            log.info("异步调用用户服务:userId={}", userId);
            // 模拟服务耗时(企业级可删除,仅测试用)
            try { Thread.sleep(150); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
            return userFeignClient.getUserById(userId);
        }, orderAsyncExecutor)
                .orTimeout(200, TimeUnit.MILLISECONDS) // 超时控制
                .exceptionally(ex -> {
                    log.error("用户服务调用失败:userId={}", userId, ex);
                    return UserDTO.builder().userId(userId).userName("用户信息暂未获取").build();
                });

        // 3. 异步调用商品服务
        CompletableFuture<ProductDTO> productFuture = CompletableFuture.supplyAsync(() -> {
            log.info("异步调用商品服务:productId={}", productId);
            try { Thread.sleep(180); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
            return productFeignClient.getProductById(productId);
        }, orderAsyncExecutor)
                .orTimeout(200, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> {
                    log.error("商品服务调用失败:productId={}", productId, ex);
                    return ProductDTO.builder().productId(productId).productName("商品信息暂未获取").build();
                });

        // 4. 异步调用物流服务
        CompletableFuture<LogisticsDTO> logisticsFuture = CompletableFuture.supplyAsync(() -> {
            log.info("异步调用物流服务:orderId={}", orderId);
            try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
            return logisticsFeignClient.getLogisticsByOrderId(orderId);
        }, orderAsyncExecutor)
                .orTimeout(200, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> {
                    log.error("物流服务调用失败:orderId={}", orderId, ex);
                    return LogisticsDTO.builder().orderId(orderId).logisticsStatus("物流信息暂未获取").build();
                });

        // 5. 异步调用优惠券服务
        CompletableFuture<List<CouponDTO>> couponFuture = CompletableFuture.supplyAsync(() -> {
            log.info("异步调用优惠券服务:orderId={}", orderId);
            try { Thread.sleep(160); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
            return couponFeignClient.getCouponsByOrderId(orderId);
        }, orderAsyncExecutor)
                .orTimeout(200, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> {
                    log.error("优惠券服务调用失败:orderId={}", orderId, ex);
                    return Collections.emptyList();
                });

        // 6. 等待所有异步任务完成(企业级:用allOf+join,避免阻塞主线程)
        CompletableFuture.allOf(userFuture, productFuture, logisticsFuture, couponFuture)
                .exceptionally(ex -> {
                    log.error("订单详情聚合任务异常", ex);
                    return null;
                })
                .join();

        // 7. 聚合结果(企业级:用get()时已无阻塞风险,因为前面已join)
        try {
            builder.user(userFuture.get())
                   .product(productFuture.get())
                   .logistics(logisticsFuture.get())
                   .coupons(couponFuture.get())
                   .totalCost(System.currentTimeMillis() - start);
        } catch (Exception e) {
            log.error("聚合订单详情结果异常", e);
        }

        return builder.build();
    }
}
步骤6:控制器(对外接口)
less 复制代码
@RestController
@RequestMapping("/api/order")
@Slf4j
public class OrderDetailController {
    @Resource
    private OrderDetailService orderDetailService;

    /**
     * 订单详情查询接口(企业级:GET请求+参数校验)
     */
    @GetMapping("/detail")
    public ResponseEntity<OrderDetailDTO> getOrderDetail(@RequestParam @NotNull Long orderId) {
        OrderDetailDTO detail = orderDetailService.getOrderDetail(orderId);
        return ResponseEntity.ok(detail);
    }
}
步骤7:测试验证(企业级单元测试)
less 复制代码
@SpringBootTest
@AutoConfigureMockMvc
public class OrderDetailControllerTest {
    @Resource
    private MockMvc mockMvc;

    // Mock Feign客户端(避免依赖真实微服务)
    @MockBean
    private OrderBaseFeignClient orderBaseFeignClient;
    @MockBean
    private UserFeignClient userFeignClient;
    @MockBean
    private ProductFeignClient productFeignClient;
    @MockBean
    private LogisticsFeignClient logisticsFeignClient;
    @MockBean
    private CouponFeignClient couponFeignClient;

    @BeforeEach
    void setUp() {
        // Mock返回值(模拟各服务正常响应)
        Mockito.when(orderBaseFeignClient.getOrderBase(10001L))
                .thenReturn(OrderBaseDTO.builder()
                        .orderId(10001L)
                        .orderStatus("已支付")
                        .createTime(LocalDateTime.of(2025, 12, 1, 10, 0))
                        .build());
        Mockito.when(userFeignClient.getUserById(1001L))
                .thenReturn(UserDTO.builder().userId(1001L).userName("张三").phone("13800138000").build());
        Mockito.when(productFeignClient.getProductById(2001L))
                .thenReturn(ProductDTO.builder().productId(2001L).productName("华为Mate60").price(new BigDecimal("6999")).build());
        Mockito.when(logisticsFeignClient.getLogisticsByOrderId(10001L))
                .thenReturn(LogisticsDTO.builder().orderId(10001L).logisticsStatus("已发货").expressCompany("顺丰").build());
        Mockito.when(couponFeignClient.getCouponsByOrderId(10001L))
                .thenReturn(Collections.singletonList(CouponDTO.builder().couponId(3001L).couponName("满5000减500").discount(new BigDecimal("500")).build()));
    }

    /**
     * 测试核心:验证并行调用的耗时(应≈最长单个服务耗时200ms)
     */
    @Test
    void testGetOrderDetail() throws Exception {
        // 执行请求
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/api/order/detail")
                        .param("orderId", "10001")
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn();

        // 解析响应
        String response = result.getResponse().getContentAsString();
        OrderDetailDTO dto = JSON.parseObject(response, OrderDetailDTO.class);

        // 企业级验证点
        Assertions.assertEquals(10001L, dto.getOrderId());
        Assertions.assertEquals("张三", dto.getUser().getUserName());
        Assertions.assertEquals("华为Mate60", dto.getProduct().getProductName());
        // 关键验证:并行调用耗时≈200ms(串行需150+180+200+160=690ms)
        Assertions.assertTrue(dto.getTotalCost() < 300, "并行调用耗时应小于300ms,实际:" + dto.getTotalCost() + "ms");

        log.info("订单详情接口测试通过,耗时:{}ms", dto.getTotalCost());
    }
}
测试结果(企业级输出)
ini 复制代码
2025-12-04 16:00:00.123  INFO 12345 --- [order-async-pool-1] c.e.s.service.OrderDetailService        : 异步调用用户服务:userId=1001
2025-12-04 16:00:00.124  INFO 12345 --- [order-async-pool-2] c.e.s.service.OrderDetailService        : 异步调用商品服务:productId=2001
2025-12-04 16:00:00.125  INFO 12345 --- [order-async-pool-3] c.e.s.service.OrderDetailService        : 异步调用物流服务:orderId=10001
2025-12-04 16:00:00.126  INFO 12345 --- [order-async-pool-4] c.e.s.service.OrderDetailService        : 异步调用优惠券服务:orderId=10001
2025-12-04 16:00:00.320  INFO 12345 --- [           main] c.e.s.controller.OrderDetailControllerTest : 订单详情接口测试通过,耗时:210ms

核心结论:并行调用耗时210ms,远低于串行的690ms,验证了企业级方案的有效性。


场景2:金融用户资产全景查询(批量并行)

场景描述

银行/支付平台的"用户资产全景"页面:用户登录后,需要查询账户余额、活期理财、定期理财、基金持仓、信用卡账单 5类资产,且每个品类下有多个产品(比如5个基金),若串行查询所有产品,耗时极长;用 CompletableFuture 批量并行查询,控制并行度(比如5个),既提升效率,又不打垮后端服务。

方案设计(核心差异:控制并行度)

  1. 线程池:创建"金融资产专用线程池";
  2. 批量并行:将10个基金产品拆分为2批,每批5个并行查询;
  3. 超时+降级:每个基金查询超时300ms,失败则返回"该基金暂未获取";
  4. 结果聚合:汇总所有资产,计算总资产。

核心代码(仅展示差异部分,其他同场景1)

scss 复制代码
@Service
@Slf4j
public class UserAssetService {
    @Resource
    @Qualifier("assetAsyncExecutor")
    private Executor assetAsyncExecutor;

    /**
     * 企业级:批量基金持仓查询(控制并行度)
     */
    public List<FundDTO> batchGetFunds(List<Long> fundIds, Long userId) {
        // 企业级:控制并行度为5(避免打垮基金服务)
        int parallelism = 5;
        // 拆分批量任务
        List<List<Long>> batchFundIds = Lists.partition(fundIds, parallelism);
        List<FundDTO> allFunds = new ArrayList<>();

        for (List<Long> batch : batchFundIds) {
            // 每批并行查询
            List<CompletableFuture<List<FundDTO>>> futures = batch.stream()
                    .map(fundId -> CompletableFuture.supplyAsync(() -> {
                        log.info("异步查询基金:fundId={}, userId={}", fundId, userId);
                        return fundFeignClient.getFundById(fundId, userId);
                    }, assetAsyncExecutor)
                            .orTimeout(300, TimeUnit.MILLISECONDS)
                            .exceptionally(ex -> {
                                log.error("基金查询失败:fundId={}", fundId, ex);
                                return Collections.singletonList(FundDTO.builder().fundId(fundId).fundName("基金信息暂未获取").build());
                            }))
                    .collect(Collectors.toList());

            // 等待当前批次完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            // 聚合当前批次结果
            for (CompletableFuture<List<FundDTO>> future : futures) {
                try {
                    allFunds.addAll(future.get());
                } catch (Exception e) {
                    log.error("聚合基金结果异常", e);
                }
            }
        }

        return allFunds;
    }

    /**
     * 用户资产全景查询(聚合所有资产)
     */
    public UserAssetDTO getUserAsset(Long userId) {
        long start = System.currentTimeMillis();
        UserAssetDTO.AssetDTOBuilder builder = UserAssetDTO.builder().userId(userId);

        // 1. 异步查询账户余额
        CompletableFuture<AccountDTO> accountFuture = CompletableFuture.supplyAsync(() -> accountFeignClient.getAccount(userId), assetAsyncExecutor)
                .orTimeout(300, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> AccountDTO.builder().userId(userId).balance(BigDecimal.ZERO).build());

        // 2. 异步查询活期理财
        CompletableFuture<List<FinanceDTO>> financeFuture = CompletableFuture.supplyAsync(() -> financeFeignClient.getDemandFinance(userId), assetAsyncExecutor)
                .orTimeout(300, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> Collections.emptyList());

        // 3. 异步查询批量基金(控制并行度)
        CompletableFuture<List<FundDTO>> fundFuture = CompletableFuture.supplyAsync(() -> {
            List<Long> fundIds = Arrays.asList(101L, 102L, 103L, 104L, 105L, 106L, 107L, 108L, 109L, 110L);
            return batchGetFunds(fundIds, userId);
        }, assetAsyncExecutor)
                .orTimeout(1000, TimeUnit.MILLISECONDS) // 批量任务超时稍长
                .exceptionally(ex -> Collections.emptyList());

        // 等待所有任务完成
        CompletableFuture.allOf(accountFuture, financeFuture, fundFuture).join();

        // 聚合结果+计算总资产
        try {
            AccountDTO account = accountFuture.get();
            List<FinanceDTO> finances = financeFuture.get();
            List<FundDTO> funds = fundFuture.get();

            BigDecimal totalAsset = account.getBalance()
                    .add(finances.stream().map(FinanceDTO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add))
                    .add(funds.stream().map(FundDTO::getHoldAmount).reduce(BigDecimal.ZERO, BigDecimal::add));

            builder.account(account)
                   .finances(finances)
                   .funds(funds)
                   .totalAsset(totalAsset)
                   .costTime(System.currentTimeMillis() - start);
        } catch (Exception e) {
            log.error("聚合资产异常", e);
        }

        return builder.build();
    }
}

场景3:通用非核心链路异步处理(下单后短信通知)

场景描述

企业下单/支付成功后,需要发送短信/推送通知、记录操作日志、更新统计数据,这些属于"非核心链路":核心链路只需保证下单成功,非核心链路失败不影响主流程;用 CompletableFuture 异步执行,核心链路响应更快(比如从500ms降至100ms)。

核心代码(企业级最简模板)

less 复制代码
@Service
@Slf4j
public class OrderNotifyService {
    @Resource
    @Qualifier("notifyAsyncExecutor")
    private Executor notifyAsyncExecutor;

    /**
     * 企业级:下单成功后异步发送短信(非核心链路)
     */
    public void asyncSendSms(Long orderId, Long userId, String phone) {
        // 异步执行:不阻塞主流程,核心链路直接返回"下单成功"
        CompletableFuture.runAsync(() -> {
            try {
                log.info("异步发送下单短信:orderId={}, phone={}", orderId, phone);
                // 调用短信服务(模拟耗时)
                smsFeignClient.sendSms(phone, "您的订单" + orderId + "已下单成功");
                // 记录短信发送日志
                logService.recordSmsLog(orderId, userId, phone, "SUCCESS");
            } catch (Exception e) {
                log.error("短信发送失败:orderId={}", orderId, e);
                // 企业级:失败后记录日志,后续定时重试
                logService.recordSmsLog(orderId, userId, phone, "FAIL");
            }
        }, notifyAsyncExecutor)
                .orTimeout(500, TimeUnit.MILLISECONDS)
                .exceptionally(ex -> {
                    log.error("异步短信任务异常:orderId={}", orderId, ex);
                    return null;
                });
    }

    /**
     * 核心下单接口(主流程)
     */
    public OrderDTO createOrder(OrderCreateReq req) {
        // 1. 核心链路:创建订单(数据库操作/事务)
        OrderDTO order = orderMapper.insertOrder(req);
        // 2. 非核心链路:异步发送短信(不阻塞主流程)
        asyncSendSms(order.getOrderId(), req.getUserId(), req.getPhone());
        // 3. 非核心链路:异步更新统计数据
        asyncUpdateStatistics(order.getOrderId(), req.getProductId());
        // 4. 核心链路直接返回,无需等待异步任务
        return order;
    }
}

三、总结(企业级核心要点)

1. 核心使用场景(90%企业就这3类)

  • 多服务并行聚合(订单详情、用户资产、商品详情);
  • 批量数据并行查询(批量基金、批量商品、批量订单);
  • 非核心链路异步处理(短信通知、日志记录、统计更新)。

2. 企业级落地关键

  • 线程池:按业务域隔离,用有界队列+合理拒绝策略;
  • 超时+降级:所有异步调用必须加,避免线程阻塞/结果丢失;
  • 并行度:批量场景控制并行数,避免打垮依赖服务;
  • 监控:线程池指标(活跃数、队列长度)+ 异步任务成功率必须监控。

3. 绝对禁用场景

  • 写操作/事务场景(支付、转账、库存扣减);
  • 强一致性要求的场景(比如订单状态更新);
  • 实时性要求极高的核心链路(比如秒杀下单)。

以上代码和方案是企业级落地的标准模板,你可以直接复用,只需替换Feign客户端和业务DTO为自己的实际业务即可。

相关推荐
C雨后彩虹1 小时前
最少交换次数
java·数据结构·算法·华为·面试
i***11861 小时前
【MyBatisPlus】MyBatisPlus介绍与使用
java
脑极体1 小时前
蓝河入海:Rust先行者vivo的开源之志
开发语言·后端·rust·开源
源代码•宸1 小时前
GoLang并发简单例子(goroutine + channel + WaitGroup)
开发语言·经验分享·后端·学习·golang
稚辉君.MCA_P8_Java1 小时前
Gemini永久会员 Go 返回最长有效子串长度
数据结构·后端·算法·golang
kesifan1 小时前
JAVA的线程的周期及调度
java·开发语言
李少兄1 小时前
解决 Spring Boot 中 YAML 配置文件的 `ArrayIndexOutOfBoundsException: -1` 异常
java·spring boot·后端
uup1 小时前
Java 多线程环境下的资源竞争与死锁问题
java