产品详情接口并发编排

在现代软件开发中,我们常常需要在一个接口里调用多个服务来汇总结果,这时采用并发编排能够显著提升接口性能。Java 中的 CompletableFuture 是处理异步编程和并发流的强大工具。借助它,我们可以在后台执行任务,并在任务完成后合并结果。

项目背景

假设我们正在开发电子商务系统的产品详情接口,该接口需要从多个服务获取数据,例如:

  1. 产品基本信息服务
  2. 产品库存服务
  3. 产品定价服务
  4. 用户评论服务

若串行调用这些独立服务,会影响性能。因此,我们将使用 CompletableFuture 并发调度这些服务,以提升响应性能。

项目结构

  1. Controller 层:负责接收请求和返回结果。
  2. Service 层:设定每个服务的调用逻辑。
  3. 使用 CompletableFuture 进行并发编排。

核心代码实现

1. 产品详情实体类

public class ProductDetails {
    private String basicInfo;
    private Integer stock;
    private Double price;
    private List reviews;

    // Getters and setters
}

2. Controller 层

@RestController
@RequestMapping("/api/products")
public class ProductController {

    @Autowired
    private ProductService productService;

    @GetMapping("/{productId}/details")
    public CompletableFuture<ResponseEntity<ProductDetails>> getProductDetails(@PathVariable Long productId) {
        return productService.getProductDetails(productId)
                .thenApply(ResponseEntity::ok);
    }
}

3. Service 层

@Service
public class ProductService {

    @Autowired
    private BasicInfoService basicInfoService;

    @Autowired
    private StockService stockService;

    @Autowired
    private PricingService pricingService;

    @Autowired
    private ReviewsService reviewsService;

    public CompletableFuture<ProductDetails> getProductDetails(Long productId) {
        CompletableFuture<String> basicInfoFuture = CompletableFuture.supplyAsync(() -> basicInfoService.getBasicInfo(productId));
        CompletableFuture<Integer> stockFuture = CompletableFuture.supplyAsync(() -> stockService.getStock(productId));
        CompletableFuture<Double> priceFuture = CompletableFuture.supplyAsync(() -> pricingService.getPrice(productId));
        CompletableFuture<List> reviewsFuture = CompletableFuture.supplyAsync(() -> reviewsService.getReviews(productId));

        return CompletableFuture.allOf(basicInfoFuture, stockFuture, priceFuture, reviewsFuture)
                .thenApply(voided -> {
                    try {
                        ProductDetails details = new ProductDetails();
                        details.setBasicInfo(basicInfoFuture.get());
                        details.setStock(stockFuture.get());
                        details.setPrice(priceFuture.get());
                        details.setReviews(reviewsFuture.get());
                        return details;
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
    }
}

4. 各个服务类(示例)

下面是其中一个示例服务类,其余服务类可以类似实现:

@Service
public class BasicInfoService {

    public String getBasicInfo(Long productId) {
        // 模拟调用远程服务或数据库查询以获取基本信息
        return "Product basic information for productId: " + productId;
    }
}

代码说明

  1. 产品详情实体类

    • ProductDetails 类用于封装从不同服务获取的所有产品数据。
  2. Controller 层

    • ProductController 提供获取产品详情的接口。它调用 ProductService#getProductDetails 方法,该方法返回 CompletableFuture 对象,以异步方式响应请求。
  3. Service 层

    • ProductServicegetProductDetails 方法使用 CompletableFuture.supplyAsync 并发调用各个子服务。
    • CompletableFuture.allOf 方法等待所有服务请求完成,然后从各个 CompletableFuture 中获取结果。
    • thenApply 是转换器方法,用于将异步操作的结果转换为最终的 ProductDetails 对象。
  4. 各个服务类

    • 每个服务类(如 BasicInfoServiceStockService 等)代表一个子任务,由 CompletableFuture 并发调用以提高性能。

效果

  1. 提升性能

    • CompletableFuture 提供简单方式并发多个异步任务,减少接口总响应时间。
  2. 易于维护和扩展

    • 服务之间解耦,增加新服务只需扩展 CompletableFuture 的组合逻辑,无需重构现有代码。
  3. 非阻塞的异步设计

    • 利用 CompletableFuture 的非阻塞特性,并发调用远程服务或数据库查询,有效利用系统资源。
  4. 异常处理简便

    • CompletableFuture 可通过 exceptionally 方法进行异常处理,确保系统稳定性。

这个示例展示了如何利用 CompletableFuture 进行服务调用并发编排,使接口响应更快,提升系统整体性能。在实际应用中,可根据需要进一步调整并发和处理策略。