容器部署Python requests库为何出现重复API调用:容器IP与主机IP各一次?
Docker容器中Python应用重复HTTP请求问题排查
问题现象
- 部署在Docker容器内的Python应用,每次向外部REST API发起请求时,通过
tcpdump抓包会捕获到两个HTTP请求:一个来自容器IP,另一个来自主机IP。 - 应用业务日志仅记录一次请求触发,但
urllib3组件日志显示两次HTTP连接建立及POST请求。
相关信息
抓包命令
tcpdump -i any -nn host 10.222.xx.yy
抓包结果截图
[TCP抓包结果截图]
Mockoon服务配置截图
[Mockoon配置截图]
API调用日志
2023-02-21 10:05:43,442 DEBUG app.processors.outgoing 处理消息... 2023-02-21 10:05:43,449 INFO app.processors.outgoing 向消费者发送消息,ID:1 => 交易ID:1676963144066_3084018310_3084018310 2023-02-21 10:05:43,452 DEBUG app.processors.outgoing 1 => 超时时间:5.0 2023-02-21 10:05:43,454 DEBUG urllib3.connectionpool 启动新的HTTP连接(1):10.222.yyy.xxx:9001 2023-02-21 10:05:43,490 DEBUG urllib3.connectionpool http://10.222.^^^.^^^:9001 "POST /rtt/notify HTTP/1.1" 200 2 2023-02-21 10:05:43,494 DEBUG urllib3.connectionpool 启动新的HTTP连接(1):10.222.^^^.^^^:9001 2023-02-21 10:05:43,543 DEBUG urllib3.connectionpool http://10.222.^^^.^^^:9001 "POST /rtt/notify HTTP/1.1" 200 2 2023-02-21 10:05:43,544 DEBUG app.processors.outgoing 延迟(ms):50.673 2023-02-21 10:05:43,545 INFO app.processors.outgoing 成功响应:200, {} 2023-02-21 10:05:43,573 DEBUG app.common.decorators 计时器:app.processors.outgoing: send_message_to_consumer 耗时123.77ms: 参数: () 2023-02-21 10:05:43,574 INFO app.processors.outgoing 已处理1条消息 2023-02-21 10:05:43,574 DEBUG app.common.decorators 计时器:app.processors.outgoing: process_out_messages 耗时132.18ms: 参数: ()
排查方向与解决方案
1. 调整urllib3重试策略
从日志可见,第一次请求返回200后仍触发了第二次请求,大概率是urllib3默认重试机制被误触发。可能因响应头、网络波动或超时配置导致。
解决方法:
显式配置重试规则,禁用不必要的重试:
from urllib3 import PoolManager, Retry # 完全禁用重试 http = PoolManager(retries=Retry(total=0)) # 或仅允许特定请求方法/状态码重试 http = PoolManager(retries=Retry(total=1, allowed_methods=["GET"], status_forcelist=[500, 502]))
2. 检查Docker网络配置
抓包出现主机IP请求,需排查容器网络模式或路由规则是否导致请求重复转发:
- 若使用
host模式,确认是否存在主机层面的请求重定向规则; - 若使用默认
bridge模式,检查docker run命令是否有重复端口映射,或主机iptables是否存在针对目标API的重复转发规则。
解决方法:
切换为默认bridge网络模式,清理无效的端口映射及iptables规则。
3. 追踪代码隐式调用
业务日志仅记录一次请求,但urllib3有两次请求,可能是第三方库、装饰器或钩子函数发起了隐式请求:
解决方法:
在请求发送处添加调用栈日志,或用pdb断点跟踪:
import traceback def send_api_request(): print(f"请求触发栈:\n{''.join(traceback.format_stack())}") # 原有请求发送逻辑
4. 校验API响应有效性
Mockoon返回响应长度仅为2,可能是空白或不符合客户端预期格式,导致客户端触发重试:
解决方法:
调整Mockoon响应内容为客户端预期格式(如有效JSON),观察是否仍出现重复请求。
内容的提问来源于stack exchange,提问作者Ezra Nkayamba
相关产品推荐
相关产品推荐

