abc`1 2024-02-12 18:15 采纳率: 73.7%
浏览 25

对接第三方接口的一致性问题

用户在界面点击提交按钮进行提交任务,我们会实时用httpclient调用b系统的创建任务接口,在b系统上创建任务。
但是由于网络问题,我们httpclient报异常了,用户自然看到提交任务失败了。
但实际上b系统已经成功创建任务了,因为我们httpclient报错,数据库并没有关联到b系统的这个任务。b系统的这个任务就是“幽灵任务”了。
一般是怎么处理这种问题的?(重试解决的是提交任务因网络失败的问题,但是解决不了“幽灵任务”的问题)

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-02-12 18:17
    关注

    引自免费微信小程序:皆我百晓生

    处理第三方接口调用的一致性问题,特别是防止出现“幽灵任务”的情况,通常需要采用幂等性和补偿机制的设计方案。以下是一种可能的解决方案:

    1. 幂等性设计 在B系统中,创建任务的接口应该设计为幂等的。这意味着多次调用该接口对系统的影响与一次调用相同。具体到您的场景中,当A系统因为网络问题未能收到成功响应时,可以在后续某个合适的时间点(例如通过定时任务或重试机制)再次发起请求,而不会导致任务被重复创建。

    // 假设这是B系统的创建任务接口,使用唯一任务ID确保幂等性
    @POST
    @Path("/create-task")
    public Response createTask(@QueryParam("taskId") String taskId, TaskInfo taskInfo) {
        if (taskExists(taskId)) {
            // 如果任务已存在,则返回成功,表明幂等操作完成
            return Response.ok().build();
        } else {
            // 正常创建任务,并记录相关信息
            createNewTask(taskId, taskInfo);
            return Response.created(new URI("/tasks/" + taskId)).build();
        }
    }
    

    2. 异步处理和事务回查 在A系统调用B系统接口后,可以将请求放入消息队列,通过异步消费者来处理回调和确认机制。

    • A系统将任务创建请求发送至消息队列。
    • 消费者从消息队列取出请求并尝试调用B系统的创建任务接口。
    • 若调用成功,消费者更新A系统的数据库关联信息。
    • 若调用失败,将消息重新放回队列等待下次重试,或者进入死信队列进行人工干预。

    3. 补偿机制 对于已经发生异常但实际在B系统创建成功的任务,可以通过定期的数据校验(比如全量或增量数据对比)来发现并修正这种不一致状态。这通常涉及到在A系统中实现一个同步或校验服务,它可以查询B系统的任务状态,并据此更新A系统的数据库。

    // 假设这是一个定时任务或服务,用于同步A、B系统间的任务状态
    @Service
    public class DataConsistencyService {
    
        @Autowired
        private BSystemApiClient bSystemApiClient;
    
        @Autowired
        private ASystemRepository aSystemRepository;
    
        @Scheduled(cron = "0 0/15 * * * ?") // 每15分钟执行一次
        public void syncTasks() {
            List<TaskInfo> tasksInBSystem = bSystemApiClient.getAllTasks();
            
            for (TaskInfo task : tasksInBSystem) {
                if (!aSystemRepository.existsByTaskId(task.getId())) {
                    // 在A系统中补充创建或关联此任务
                    aSystemRepository.createOrUpdateTask(task);
                }
            }
        }
    }
    
    

    以上代码仅为示例,并未考虑所有细节,如具体的错误处理、数据库操作以及httpclient的配置等。在实际应用中,请根据自身业务需求和技术栈进行调整优化。同时,引入分布式事务框架(如Seata、TCC模式)也能更好地解决跨系统的数据一致性问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月12日

悬赏问题

  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计