非常奇怪的 requests 库请求 flask 的问题,会有一个超时

2019-12-26 10:57:20 +08:00
 ksc010
>>> flask.__version__
'1.0.2'
>>> requests.__version__
'2.22.0'

-------------------

requests 请求 flask 提供的接口 会有一个 2s 的延迟,即使这个接口嘛都不做 直接返回'ok'

也就是 requests 开始请求到收到响应的数据至少需要 2s
但是 若给 requests 设置一个超时参数比如 1s 这延迟就会减少到 1s
设置 0.2 就会减少到 0.2
requests.post(apiurl, json=jsondata, timeout=(0.2, 3.2))
这个延迟应该是 connect 的超时
当然直接 post(xxxxx, timeout=0.2) 也可以
4778 次点击
所在节点    Python
18 条回复
ksc010
2019-12-26 11:04:51 +08:00
还有一个情况就是
requests 请求 nginx 正常
浏览器请求 flask 正常
privatezcoding
2019-12-26 11:04:58 +08:00
你电脑是不是开了代理
ksc010
2019-12-26 11:06:50 +08:00
@privatezcoding 对 但是不是系统代理 需要显示的指定端口
wuwukai007
2019-12-26 11:20:50 +08:00
打个断点看下 flask 接受请求的事件是不是延迟了,用 urllib 和 curl 都请求下试试呢
gwy15
2019-12-26 11:27:10 +08:00
我上次写单元测试也遇到这个问题,后来发现是 DNS 花了 2s。楼主换成裸 ip 试试
ksc010
2019-12-26 11:28:02 +08:00
@wuwukai007
curl 和浏览器一样 没有延迟

requests 就不行
requests.get('http://localhost:8080',timeout=2).text 就这一行代码 明显感觉延迟了

--------------------
flask 启动参数
app.run(port=self.port, host=self.host, threaded=True)
lenqu
2019-12-26 11:28:05 +08:00
或者 f12 查看一下开发工具里统计的延迟
ksc010
2019-12-26 11:31:32 +08:00
@gwy15 擦 果然是
localhost 换成 127.0.0.1 就好了
gwy15
2019-12-26 11:31:55 +08:00
@ksc010
我上次就是这么写的,localhost 换成 127.0.0.1 之后就没问题了
lenqu
2019-12-26 11:34:37 +08:00
@gwy15 难道是返回 fstab 解析的问题?
smallpython
2019-12-26 11:39:57 +08:00
把 localhost 转换为 127.0.0.1 这件事情是谁做的?为什么会有两秒的延迟
ksc010
2019-12-26 11:41:38 +08:00
@gwy15 之所以没往 dns 这方面想
是因为记得 请求内网服务器上的接口也是慢(通过内网 ip 10.1.1.22:8080 )
然后一直测试本地的接口(通过 localhost:8080 )
在你说直接使用 ip 之后 又测试了下内网服务器接口 发现速度正常了(这个可能是其他的问题引起的 但是现在没有复现)

总之非常感谢
wybhdxfx
2019-12-26 12:06:26 +08:00
学习了,平常我也习惯用 127.0.0.1,少用 localhost。
ClericPy
2019-12-26 13:36:31 +08:00
看标题没看懂... 看到最后才知道说的是啥...

也不知道什么时候开始, Windows10 和 macOS 默认的 hosts 里都有一句 ipv6 版本的 localhost, 不确定是自带的还是被什么改的
gwy15
2019-12-26 13:45:48 +08:00
我跟踪了一下,跟踪到了
`urllib3.util.connection.create_connection`
这个函数里面。

这个函数做的是根据 host 和 port 建立 socket 连接。当使用 localhost 的时候,会调用
`for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM)`
这样一个循环。对于 `localhost`,会返回两个结果:

+ ::1 (ipv6 下的 localhost)
+ 127.0.0.1 (ipv4 下的 localhost)

根据循环,会首先尝试连接 `::1`,而如果 flask 使用的是默认的 host 或是 0.0.0.0,只会监听 ipv4 的请求,因此 ipv6 会抛出 NewConnectionError,而后继续尝试 ipv4 的请求。这就是两秒延迟的原因。

解决方法:
+ 使用 app.run(host='::') 调试,使 flask 监听 ipv6,这样第一个尝试的 `::1` 也可以正常连接。
+ 使用 requests.get('127.0.0.1'), 避免 DNS 解析。
nznd
2019-12-26 14:03:31 +08:00
让我想到了这个帖子 /t/623596
从这之后我的本地测试全部是指定内网 ip, 不再用 localhost 了
deplives
2019-12-29 17:09:08 +08:00
很早之前在 sof 上我就看到一个问题大概类似,底下回答基本上都是不要用 localhost 虽然那个问题我没遇到过,但从那之后我也不用 localhost 了
ksc010
2020-09-24 17:55:55 +08:00
一年后又遇到相同的问题,翻了下这个帖子想起来原因了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/632462

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX