11

我写了一个烧瓶应用程序。当我将它部署在远程服务器中时,我发现它非常慢。所以,我用它做了一些分析实践。请看下面的图片:

我用来分析的代码是:

#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)

图片1

远程服务器中进行分析。也许瓶颈是_socket.getaddrinfo

在此处输入图像描述

图二

在本地机器中进行分析。没有发现瓶颈。

在此处输入图像描述

图三

有时,即使在远程服务器中,也没有发现瓶颈。没有_socket.getaddrinfo找到。诡异的! 在此处输入图像描述

我也在远程服务器 python shell 中使用cProfile. 看看这个:


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被调用?因为它减慢了我的网站速度,这让我很伤心。

4

3 回答 3

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.

与 Digital Ocean 支持合作,并怀疑这是一个 DNS 问题,工作的解决方案是改变(in /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 运营)认为它讨厌我,但目前我和 Google 的 DNS 都很酷。

更新:我的同事 Karl 建议我继续使用绑定设置本地 DNS 缓存服务器,以防止 Google 的 DNS 也讨厌我。这个链接非常有帮助。

于 2014-08-25T19:33:12.720 回答
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。

于 2013-08-01T08:26:41.567 回答
1

我在不久的过去遇到了同样的问题。为了查看导致缓慢的原因,我决定查看我的哪些端点被请求更多,哪些是瓶颈。为此,我创建了一个分析请求的工具。它也可以帮助你,看看它https://github.com/muatik/flask-profiler

于 2015-10-26T13:41:24.380 回答