Flutter应用网络不稳定时S2服务器重复生成订单问题求助
解决S2服务器重复订单问题的方案
核心问题分析
网络不稳定时出现重复订单,本质是分布式系统下的请求重试导致的幂等性缺失——可能是Flutter客户端因超时重发请求到S1,或是S1因S2响应超时重复调用S2,而S2没有校验重复请求的机制。
具体解决步骤
1. 给所有请求添加唯一幂等标识
- Flutter端:用户下单时生成全局唯一的
request_id(比如UUID),同一次下单操作仅生成一个ID,可暂存本地缓存,直到收到S1明确响应后再清除,请求时携带该ID。 - S1(Laravel):收到请求后先检查本地是否已处理过该
request_id,若已处理直接返回历史结果;未处理则调用S2时传递该ID。 - S2(Zend Framework):接收请求时校验
request_id是否已存在于订单记录,若存在直接返回成功响应,不再重复创建订单。
2. 调整各环节超时与重试策略
- Flutter端:设置10-15秒的合理超时时间,禁止自动重试,改为让用户手动触发(同时显示“订单提交中,请稍候”提示,避免用户重复点击);若必须自动重试,需基于
request_id确保仅重试同一请求,且限制重试次数(最多2次)。 - S1(Laravel):调用S2时设置8-10秒超时,仅在确认S2未收到请求(如连接超时、无响应)时重试,且重试时携带同一
request_id;收到S2非超时类错误响应时不重试。
Laravel示例代码片段:$requestId = $request->header('X-Request-ID'); // 检查本地是否已处理该请求 if (OrderLog::where('request_id', $requestId)->exists()) { return response()->json(['status' => 'success', 'message' => '订单已处理']); } // 调用S2时携带幂等ID $response = Http::withHeaders(['X-Request-ID' => $requestId]) ->timeout(8) ->post('https://s2.example.com/api/record-sale', $orderData);
3. S2端双重去重校验
除了request_id校验,还可结合用户ID+商品ID+下单时间做辅助拦截——比如拦截5分钟内同一用户同一商品的重复订单,双重保障避免重复创建。
4. 增加请求状态持久化
S1调用S2前,先将订单状态标记为“待处理”写入数据库;收到S2成功响应后更新为“已完成”;若调用超时,通过定时任务查询S2订单状态再同步本地状态,避免因超时触发重复调用。
内容的提问来源于stack exchange,提问作者Hyacinthe Njimbong
相关产品推荐
相关产品推荐

