当前位置: 首页 > article >正文

在java 项目 springboot3.3 中 调用第三方接口(乙方),如何做到幂等操作(调用方为甲方,被调用方为乙方)? 以及啥是幂等操作?

什么是幂等操作?

幂等性(Idempotence) 是指一个操作无论执行一次还是多次,对系统状态产生的影响都是相同的。在分布式系统中,由于网络不稳定、超时重试等因素,接口可能被重复调用,幂等设计能确保重复请求不会导致意外结果。

以扣款通知为例:
  • 场景:用户支付成功后,甲方(电商平台)调用乙方(支付公司)的扣款通知接口。
  • 幂等要求
    ✅ 用户支付100元,无论通知发送1次还是N次,乙方只扣款一次。
    ❌ 若乙方未做幂等处理,可能导致重复扣款。

甲方(Spring Boot 调用方)幂等实现方案

甲方需确保:即使重试多次,乙方接口只处理一次业务。核心思路是通过唯一标识(如订单号)控制请求。

1. 生成唯一幂等键(Idempotency Key)
  • 为每个业务请求生成全局唯一ID(如UUID业务ID+时间戳),并在调用乙方时传递该值。
  • 示例格式:
    String idempotencyKey = "ORDER_20240604120000_123456";
    
2. 在请求头/体中传递幂等键
  • 乙方接口需支持接收幂等键(通常放在HTTP Header):
    HttpHeaders headers = new HttpHeaders();
    headers.add("Idempotency-Key", idempotencyKey); // 行业通用做法
    
3. 甲方本地记录请求状态
  • 在数据库中存储每次请求的幂等键和状态:
    idorder_ididempotency_keystatusresponse
    11001KEY_ABC123SUCCESS{…}
  • 调用前检查:若该幂等键已成功,则直接返回历史结果,不再调用乙方。
4. 重试机制结合幂等键
  • 使用Spring Retry在失败时自动重试(保持相同幂等键):
    import org.springframework.retry.annotation.Retryable;
    import org.springframework.retry.annotation.Backoff;@Service
    public class PaymentService {@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))public void notifyPayment(String orderId, String idempotencyKey) {// 调用乙方接口(携带幂等键)}
    }
    
5. 完整代码示例(Spring Boot 3.3)
@Service
public class PaymentService {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate PaymentRecordRepository repository; // 数据库访问层@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000))@Transactionalpublic void notifyPaymentSuccess(String orderId) {// 1. 生成或获取幂等键(如从数据库读取)String idempotencyKey = generateIdempotencyKey(orderId);// 2. 检查是否已处理过PaymentRecord record = repository.findByIdempotencyKey(idempotencyKey);if (record != null && "SUCCESS".equals(record.getStatus())) {return; // 已成功,直接返回}// 3. 调用乙方接口HttpHeaders headers = new HttpHeaders();headers.add("Idempotency-Key", idempotencyKey);Map<String, String> body = Map.of("orderId", orderId, "amount", "100.00");HttpEntity<Map<String, String>> request = new HttpEntity<>(body, headers);try {ResponseEntity<String> response = restTemplate.postForEntity("https://third-party.com/api/debit", request, String.class);// 4. 保存请求结果savePaymentRecord(orderId, idempotencyKey, "SUCCESS", response.getBody());} catch (Exception e) {savePaymentRecord(orderId, idempotencyKey, "FAILED", e.getMessage());throw e; // 触发重试}}private String generateIdempotencyKey(String orderId) {// 实际业务中可组合: 业务前缀 + 订单ID + 操作类型return "PAY_" + orderId + "_DEBIT";}private void savePaymentRecord(String orderId, String key, String status, String response) {PaymentRecord record = new PaymentRecord();record.setOrderId(orderId);record.setIdempotencyKey(key);record.setStatus(status);record.setResponse(response);repository.save(record);}
}

乙方(第三方)的幂等责任

甲方依赖乙方的接口实现幂等性,乙方需:

  1. 接收幂等键:通过Header或Body获取甲方传递的Idempotency-Key
  2. 存储请求状态:在自身系统记录该键对应的处理结果。
  3. 拒绝重复请求
    • 若相同幂等键的请求已成功,直接返回历史结果。
    • 若相同幂等键的请求在处理中,返回409 Conflict

关键设计原则

措施目的
唯一幂等键全局标识请求,避免业务参数冲突(如订单号可能重复提交不同操作)
前置状态检查调用乙方前本地校验,减少无效请求
重试+相同幂等键确保重试时乙方识别为同一请求
乙方幂等支持甲方方案生效的前提,需与乙方约定接口规范

💡 注意事项

  • 幂等键需在业务维度唯一(例如退款和支付使用不同前缀)
  • HTTP方法选择:POST是非幂等的,但通过幂等键可使其具备幂等性
  • 网络超时场景:甲方可能未收到响应,但乙方已处理,因此需依赖乙方返回结果更新状态
http://www.lryc.cn/news/2401397.html

相关文章:

  • 贪心算法应用:集合划分问题详解
  • electron下载文件
  • Neo4j 数据导入:原理、技术、技巧与最佳实践
  • 数论~~~
  • web第十次课后作业--Mybatis的增删改查
  • 贪心算法应用:集合覆盖问题详解
  • BLOB 是用来存“二进制大文件”的字段类型
  • 5.Declare_Query_Checking.ipynb
  • 【知识点】第7章:文件和数据格式化
  • NetSuite Bundle - Dashboard Refresh
  • AI+3D 视觉重塑塑料袋拆垛新范式:迁移科技解锁工业自动化新高度
  • 智慧赋能:移动充电桩的能源供给革命与便捷服务升级
  • 【项目实践】SMBMS(Javaweb版)(三)登出、注册、注销、修改
  • 斐波那契数列------矩阵幂法
  • 【Go语言基础【四】】局部变量、全局变量、形式参数
  • DeepSeek 赋能车路协同:智能交通的破局与重构
  • RabbitMQ 的异步化、解耦和流量削峰三大核心机制
  • Ubuntu 25.10 将默认使用 sudo-rs
  • Maven​​ 和 ​​Gradle​​ 依赖管理的详细说明及示例,涵盖核心概念、配置方法、常见问题解决和工具对比。
  • 【Web应用】若依框架:基础篇21二次开发-页面调整
  • 【 java 基础知识 第一篇 】
  • CVE-2020-17518源码分析与漏洞复现(Flink 路径遍历)
  • Excel表格批量下载 CyberWin Excel Doenlaoder 智能编程-——玄武芯辰
  • 可编辑PPT | 基于大数据中台新能源智能汽车应用解决方案汽车大数据分析与应用解决方案
  • 【统计方法】基础分类器: logistic, knn, svm, lda
  • AtomicInteger原子变量和例题
  • simulink有无现成模块可以实现将三个分开的输入合并为一个[1*3]的行向量输出?
  • k8s集群安装坑点汇总
  • Selenium 和playwright 使用场景优缺点对比
  • 从 Stdio 到 HTTP SSE,在 APIPark 托管 MCP Server