企業內部系統常需接入第三方數據(如攜程接藝龍機票、美團接去哪兒酒店)。本文以「第三方團購接入 Open API」為例,系統闡述架構分層、異步化選型、冪等設計、異常治理、安全體系與問題排查機制的落地經驗。

分層理由:職責單一、依賴倒置、便於單獨擴展/替換(如未來 Web 層遷移至 Gateway)。
| 方案 | 核心機制 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| 線程池 + ExecutorService | 提交 Runnable 任務 | 簡單、無額外依賴 | 應用重啟任務丟失、無重試、難監控 | 極簡內部異步、可容忍丟失 |
| Spring Event + 重寫 multicastEvent | 發布/訂閱,異步執行監聽器 | 業務解耦、代碼內聚 | 同樣無持久化、重啟丟失 | 模組化單體應用、非核心流程 |
| 消息隊列 (MQ) | 生產者發送 → Broker 持久化 → 消費者拉取 | 持久化不丟失、削峰填谷、天然重試、可監控 | 引入基礎設施複雜度、需處理重複消費 | 核心業務、金融/訂單、高可用要求 |
最終選型:MQ(如 RabbitMQ/Kafka/RocketMQ),保證「至少一次投遞」語義。
-- 表結構
version INT DEFAULT 0
-- 生產者發送消息前
UPDATE tuan_order SET version = version + 1 WHERE id = ? AND version = ?;
-- 消費者處理
UPDATE tuan_order SET ..., version = version + 1 WHERE id = ? AND version = ?;
-- 影響行數=0 視為版本衝突,拋棄或重試
確保「只處理最新版本、不重複處理、不覆蓋舊數據」。
// 1. 錯誤碼枚舉(單一來源)
public enum ErrorCode {
PARTNER_NOT_FOUND(2001, "第三方不存在"),
SIGN_VERIFY_FAIL(2002, "簽名驗證失敗"),
IDEMPOTENT_CONFLICT(2003, "冪等衝突,請勿重複提交");
private final int code; private final String msg;
}
// 2. 業務異常(攜帶錯誤碼)
public class BizException extends RuntimeException {
private final ErrorCode errorCode;
public BizException(ErrorCode ec) { super(ec.getMsg()); this.errorCode = ec; }
}
// 3. 業務代碼拋出
if (partner == null) throw new BizException(ErrorCode.PARTNER_NOT_FOUND);
// 4. AOP 統一攔截
@Aspect
@Component
public class ExceptionHandlerAspect {
@Around("execution(* com.openapi.service..*(..))")
public Object handle(ProceedingJoinPoint pjp) {
try { return pjp.proceed(); }
catch (BizException e) { return buildResp(e.getErrorCode()); }
catch (Exception e) { log.error("系統異常", e); return buildResp(ErrorCode.SYS_ERROR); }
}
}
收益:錯誤碼集中管理、業務代碼零 try-catch、響應格式統一、易擴展國際化。
Open API 看似簡單的 HTTP 接口,背後涉及架構分層、異步可靠性、冪等正確性、異常治理、安全合規、可觀測性等多維工程課題。**「小功能、大體系」**,唯有體系化思考才能構建穩健可演進的對接平台。