我写了一个烧瓶应用程序。当我在远程服务器中部署它时,我发现它非常慢。 所以,我用它做了一些分析实践。 请看下面的图片:
我用于分析的代码是:
#coding: utf-8
from werkzeug.contrib.profiler import ProfilerMiddleware
from app import app
app.config['PROFILE'] = True
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions = [30])
app.run(debug = True)
远程服务器中的分析。
也许瓶颈是_socket.getaddrinfo
在本地计算机中进行分析。 没有发现瓶颈。
有时,即使在远程服务器中,也没有发现瓶颈。找不到_socket.getaddrinfo
。奇怪的!
我使用cProfile
在远程服务器python shell中进行了分析。
看看这个:
In [10]: cProfile.run("socket.getaddrinfo('easylib.gdufslib.org', 80, 0, 0, socket.SOL_TCP)")
3 function calls in 8.014 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 8.014 8.014 :1()
1 8.014 8.014 8.014 8.014 {_socket.getaddrinfo}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
In [11]: cProfile.run("socket.getaddrinfo('easylib.gdufslib.org', 80, 0, 0, socket.SOL_TCP)")
3 function calls in 8.009 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 8.009 8.009 :1()
1 8.009 8.009 8.009 8.009 {_socket.getaddrinfo}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
也许有一个事实是,做一些dns resolve
工作需要花费很多时间,而我自己也无法改变这一点。
任何人都可以告诉我:为什么_socket.getaddrinfo
被调用,为什么有时不被调用?
如何阻止调用_socket.getaddrinfo
?因为它减慢了我的网站,让我感到悲伤。
答案 0 :(得分:7)
我刚刚在Digital Ocean的一个专用盒子上运行的Flask应用程序中遇到了这个问题,所以我会发布解决方案以防其他人在将来遇到这个问题。
我几天前注意到,对GitHub的API请求疯狂慢,有时需要10到20秒。但在本地运行我的应用程序没有任何问题。我描述了我的应用,socket.getaddrinfo
确实是罪魁祸首:
1 15058.431 15058.4310 15058.431 15058.4310 {_socket.getaddrinfo}
1 26.545 26.5450 26.545 26.5450 {_ssl.sslwrap}
1 23.246 23.2460 23.246 23.2460 {built-in method do_handshake}
4 22.387 5.5968 22.387 5.5968 {built-in method read}
1 7.632 7.6320 7.632 7.6320 {method 'connect' of '_socket.socket' objects}
103 4.995 0.0485 7.131 0.0692 <s/werkzeug/urls.py:374(url_quote)>
2 2.459 1.2295 2.578 1.2890 <ssl.py:294(close)>
36 1.495 0.0415 10.548 0.2930 <s/werkzeug/routing.py:707(build)>
859 1.442 0.0017 1.693 0.0020 {isinstance}
.... etc.
使用数字海洋支持,并怀疑它在某种程度上是一个DNS问题,工作解决方案是改变(在/etc/resolv.conf
)
nameserver 4.2.2.2
nameserver 8.8.8.8
到
nameserver 8.8.4.4
nameserver 8.8.8.8
无论出于何种原因,4.2.2.2
(由Level3运行)决定它讨厌我,但暂时我和谷歌的DNS很酷。
更新:我的同事Karl建议我继续设置一个带有bind的本地DNS缓存服务器,以防止Google的DNS也讨厌我。 This link was super helpful.
答案 1 :(得分:1)
我认为这是由于远程主机没有缓存它的DNS查找或由于IPv6的问题而导致getaddrinfo缓慢所致。
尝试此(几次)来测试您的名称服务器是否正在缓存:
$ time host easylib.gdufslib.org
并测试在强制使用IPv4时查找是否更快:
import socket
socket.getaddrinfo("easylib.gdufslib.org", 80, socket.AF_INET, 0, socket.SOL_TCP)
如果它是由第一个引起的,您可以安装本地缓存名称服务器,或者只修复现有的名称服务器缓存。如果后者是原因,您可以尝试在代码和库中修复它,或者如果不使用它,则在主机上禁用IPv6。
答案 2 :(得分:0)
我在近期遇到过同样的问题。为了看看导致缓慢的原因,我决定看看哪些端点更多被请求以及哪些端点是瓶颈。为此,我创建了一个分析请求的工具。它也可以帮助你,看看它https://github.com/muatik/flask-profiler