快速失败(Fail Fast)

快速失败是一种防御性编程策略:尽早发现问题,尽早失败,而不是带着错误继续执行。

快速失败 vs 快速返回

flowchart LR
    subgraph 快速失败
        A["前置检查"] --> |"失败| B["立即抛出异常"]
        B --> C["快速结束"]
    end

    subgraph 慢速失败
        D["执行大量逻辑"] --> E["最后检查"]
        E --> |"失败| F["返回错误"]
        F --> G["消耗了大量资源"]
    end

快速失败示例

FailFastExample.java
public class OrderService {

    public Order createOrder(Long userId, Long productId, int quantity) {
        // 快速失败:前置检查
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        if (productId == null) {
            throw new IllegalArgumentException("商品ID不能为空");
        }

        if (quantity <= 0) {
            throw new IllegalArgumentException("数量必须大于0");
        }

        // 检查库存
        if (!inventoryService.checkStock(productId, quantity)) {
            throw new InsufficientStockException("库存不足");
        }

        // 检查用户状态
        User user = userService.getUser(userId);
        if (!user.isActive()) {
            throw new UserInactiveException("用户账号已禁用");
        }

        // 执行创建订单逻辑
        return doCreateOrder(userId, productId, quantity);
    }
}

快速失败与容错

快速失败和容错并不矛盾:

  • 快速失败:在问题发生时立即失败,不让错误传播
  • 容错:在故障发生时优雅降级,继续提供服务
FailFastAndFaultTolerance.java
public Result processRequest(Request request) {
    // 快速失败:参数校验
    validateRequest(request);

    // 容错:调用可能失败的服务
    try {
        return callService(request);
    } catch (ServiceException e) {
        // 容错:降级处理
        return getDegradedResult(request);
    }
}

本章总结

核心要点

  1. 快速失败尽早暴露问题:不带着错误继续执行
  2. 前置检查是关键:在执行前验证所有前置条件
  3. 快速失败和容错互补:快速失败防错误传播,容错保服务可用