Django项目requests.post重复发请求致重复入库、连接报错排查
问题背景
项目基于Django框架开发,views.py中定义的功能函数负责向指定站点API发送POST请求,运行时出现三类异常:
- 接口响应速度极慢
- 抛出ConnectionError错误
- POST请求被重复发送,目标站点数据库最终生成多条重复记录
初步排查未发现代码中存在显式循环逻辑,需定位问题根源。
相关代码
views.py
@login_required(login_url='login-main') def send_program_to_orchard(request, orchard_pk, pk, user_pk): services.send_program_to_orchard(orchard_pk, pk) return redirect(request.path)
services.py
def make_json(program_id): program = Program.objects.get(id=program_id) program_substances = ProgramSubstance.objects.filter(program=program) response = { 'program_number': program.number, 'program_substances': [] } for each in program_substances: response['program_substances'].append({'date': each.date.isoformat(), 'substance': each.substance, 'dose': float(each.dose), 'measurement': each.measurement, 'comment': each.comment}) return json.dumps(response) def send_program_to_orchard(orchard_pk, program_pk): orchard = Orchard.objects.get(id=orchard_pk) headers = {'Authorization': f'Token {orchard.API_token}'} data = {'data': make_json(program_pk)} requests.post(orchard.program_API, headers=headers, data=data)
问题根源
三个问题叠加导致所有异常:
- 重定向路径配置错误:视图执行完发送逻辑后,直接
redirect(request.path)跳转回当前视图对应的路径。浏览器收到302重定向响应后,会再次请求当前路径,重新触发完整的发送逻辑,哪怕第三方接口响应正常,也会因为重定向循环多次触发POST请求,直到达到浏览器最大重定向次数限制才会终止。 - HTTP请求未配置超时时间:
requests.post()未传入timeout参数,默认配置下请求会无限等待第三方接口响应,直接导致页面加载速度极慢,等待时长超出系统限制时就会抛出ConnectionError超时错误。 - 同步阻塞逻辑放大重试概率:第三方接口请求放在视图响应流程中同步执行,接口耗时直接决定用户请求的响应时长。等待过程中如果出现网络波动、用户手动刷新页面、反向代理超时重试,都会额外触发新的POST请求,进一步增加重复提交的次数。
修复方案
按优先级依次调整:
- 修正重定向目标,发送操作完成后不要跳转回当前触发发送的路径,重定向到不包含提交逻辑的业务页面(比如果园程序列表页、程序详情页),从根本上切断重定向循环触发重复提交的路径。
- 给所有第三方HTTP请求加上明确的超时配置,避免无限等待:
# 元组第一个值为连接超时时间,第二个值为读取超时时间,单位为秒,可根据业务实际情况调整 requests.post(orchard.program_API, headers=headers, data=data, timeout=(3, 10)) - 耗时的第三方接口调用不要放在同步视图中执行,接入异步任务框架(比如Celery、Django-Q)将发送逻辑放入后台队列处理,视图收到请求后把任务投递到队列即可返回响应,既可以大幅提升页面响应速度,也能避免请求阻塞导致的各类重试问题。
- 协调第三方接口做好幂等性校验,基于业务唯一标识(如果园ID+程序编号)识别重复请求,重复请求直接返回成功结果不写入数据库,从接收端兜底避免重复数据生成。
内容的提问来源于stack exchange,提问作者slmuim
相关产品推荐
相关产品推荐

