本地Flask服务器上的请求缓慢


87

刚开始在本地服务器上试用Flask时,我注意到请求/响应时间比我预期的要慢得多。

像下面这样的简单服务器需要近5秒钟才能响应。

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "index"

if __name__ == "__main__":
    app.run()

有任何想法吗?还是这只是本地服务器的方式?


它不是本地服务器,但可能与在后台运行的其他应用程序有关?
gabeio 2012年

我在i7 iMac上的OS X 10.7上运行
Meroon 2012年

1
您的回复应该花很长时间,但实际上我之前一直在摇摇晃晃,直到不成功,我才建议Bottlepy。尽管仍然检查后台进程,但是您可能在后台运行了较旧版本的服务器,从而接管了python并导致响应缓慢。也可能是您的浏览器是否在chrome和safari中发生这种情况?
gabeio 2012年

2
@Meroon的回答对我来说是正确的。但是,不要更改主机设置:我建议您仅使用127.0.0.1而不是localhost?这样就解决了问题,而无需更改系统配置。
David Bernat

Answers:


93

好吧,我知道了。对于支持ipv6的Werkzeug和os来说,这似乎是一个问题。

从Werkzeug网站http://werkzeug.pocoo.org/docs/serving/

在支持ipv6并进行了配置的操作系统(例如现代Linux系统,OS X 10.4或更高版本以及Windows Vista)上,如果访问本地服务器,某些浏览器的运行速度可能会非常慢。原因是有时ipv4和ipv6套接字都配置了“本地主机”,并且某些浏览器会尝试先访问ipv6,然后再访问ivp4。

因此,解决方法是通过从主机文件中注释掉以下行来从本地主机禁用ipv6:

::1             localhost 

一旦执行此操作,延迟问题就会消失。

我真的在挖掘Flask,并且很高兴它不是框架的问题。我知道不可能。



非常感谢!开发人员测试突然变得敏捷且反应迅速!我唯一的问题:如在Mac主机文件表明,除本地主机可能会影响我的Mac上的运作,我不知道它是否指的是这条线(或一个简单的定位本地主机127.0.0.1
大卫B.

在我的Windows 10系统上的hosts文件中,两个条目(ip4和ip6)都被注释掉了;它们由DNS系统解析。当我在“ 127.0.0.1”而不是“ localhost”上运行服务器时,速度得到了极大的提高(简单调用从2.0更改为0.003秒)
Lars

感谢您的回答!尽管我的情况有所不同(针对aiosmtpd运行鼻子2),但您的回答给了我一个提示:当我在Windows 10笔记本电脑上禁用IPv6时,速度加快了10倍或100倍!
pepoluan

87

如此处所示,将“ threaded = True”作为参数添加到app.run():http ://arusahni.net/blog/2013/10/flask-multithreading.html

例如: app.run(host="0.0.0.0", port=8080, threaded=True)

禁用ipv6的解决方案对我不起作用,但确实如此。


5
传递--threaded给我的manage.py使用也Flask-Script起作用。
Snorfalorpagus

7
对于那些通过启用线程来“修复”它的人,要当心!在这种情况下,延迟是由先前的请求未正确关闭引起的,因此现在实际上它只是在堆叠大量线程
kbtz

谢谢您,先生,我的本地主机运行得非常快。
benjaminz's

@snolflake:是否有办法知道请求是否未正确关闭?
Kylotan'5

1
我从命令行使用flask run --with-threads它解决了我的问题。
arno_v

13

@ sajid-siddiqi的解决方案在技术上是正确的,但请记住,Werkzeug中的内置WSGI服务器(打包到Flask中以及它的用途)仅是单线程的。app.run()

安装WSGI服务器以能够处理多线程行为。我对各种WSGI服务器性能进行了大量研究。您的需求可能会有所不同,但是如果您使用的只是Flask,那么我建议您使用以下Web服务器之一。

更新(2020-07-25):看起来gevent在5年前开始支持python3,在我评论它不支持之后不久,因此您现在就可以使用gevent

Gevent

您可以安装GEVENT通过PIP用命令pip install geventPIP3与命令pip3 install gevent。有关如何相应修改代码的说明,请参见:https : //flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#gevent

持有人

gevent更好,但是从我查看过的涉及实际测试的所有基准测试来看meinheld似乎是最直接,最简单的WSGI服务器。(如果您不介意进行更多配置,也可以看看uWSGI。)

您也可以使用命令通过pip3安装meinheld。从那里,查看meinheld源代码中提供的用于集成Flask的示例:https : //github.com/mopemope/meinheld/blob/master/example/flask_sample.pypip3 install meinheld

*注意:根据我对PyCharm的使用,该行from meinheld import server突出显示为错误,但是服务器将运行,因此您可以忽略该错误。


我在Flask上遇到了主要的性能问题,即使最简单的请求也需要大约0.5秒才能完成。刚刚切换到gevent,一切正常,谢谢!
gronostaj

7

而不是http://localhost:port/endpoint打电话http://127.0.0.1:port/endpoint。这为我消除了最初的500ms延迟。


对我来说,它删除了大约3秒的内容(我从0.0.0.0移到了127.0.0.1)。有人可以解释为什么以及如何运作吗?
Rotkiv

为什么以上帝的名义工作呢?从2.06秒缩短至0.002秒。浏览器能够毫无问题地使用localhost,但是在localhost上的request.get需要2秒才能解决。
Xevion

7

我的问题已通过“ threaded = True”解决,但我想提供一些背景知识来将我的问题与其他可能无法解决的问题区分开。

  1. 我的问题仅在使用python3运行Flask时出现。切换到python2,我不再遇到这个问题。
  2. 我的问题在使用Chrome访问api时才出现,这时Chrome会显示预期的屏幕,但其他所有内容(例如curl,ffx等)都挂起,直到我重新加载或关闭了Chrome选项卡,此时其他所有正在等待的内容周围返回了结果。

我最好的猜测是Chrome试图保持会话打开,而Flask阻止了后续请求。与Chrome的连接一旦停止或重置,其他所有内容都会得到处理。

就我而言,线程修复了它。当然,我现在正在浏览其他人提供的一些链接,以确保它不会引起任何其他问题。


4

threaded=True为我工作,但最终我发现问题是由于firefox上的foxyproxy引起的。由于Flask应用在本地主机上运行时,如果

  • 在Firefox上启用了foxyproxy

如果发生慢反应,

  • foxyproxy在Firefox上被禁用

  • 使用其他浏览器访问网站

我发现的唯一解决方案是禁用foxyproxy,尝试将localhost添加到代理黑名单和调整设置,但没有一个起作用。


2

我用Miheko的回应来解决我的问题。

::1 localhost已在我的主机文件上被注释掉,并且设置Threaded=true对我不起作用。每个REST请求都需要1秒来处理,而不是立即执行。

我正在使用python 3.6,并且通过使flask使用gevent作为其WSGI,使flask变得快速且能够响应REST请求。

要使用gevent,请使用 pip install gevent

之后,我使用https://gist.github.com/viksit/b6733fe1afdf5bb84a40#file-async_flask-py-L41来设置flask使用gevent。

如果链接断开,这是脚本的重要部分:

from flask import Flask, Response
from gevent.pywsgi import WSGIServer
from gevent import monkey

# need to patch sockets to make requests async
# you may also need to call this before importing other packages that setup ssl
monkey.patch_all()

app = Flask(__name__) 


# define some REST endpoints... 

def main():

    # use gevent WSGI server instead of the Flask
    # instead of 5000, you can define whatever port you want.
    http = WSGIServer(('', 5000), app.wsgi_app) 

    # Serve your application
    http.serve_forever()


if __name__ == '__main__':
    main()

threaded = True不适用于(使用python 3.6.7和邮递员),我收到VersionConflict:(greenlet 0.4.13(c:\ anaconda3 \ lib \ site-packages),Requirement.parse('greenlet> = 0.4。 14; platform_python_implementation ==“ CPython”')),我是否可以解决这个问题,谢谢
hanzgs

0

在除主机之外的其他主机上运行时localhost,也会出现此错误,因此对于某些不同的潜在问题,它们可能会表现出相同的症状。

我将我一直使用的大多数东西都切换到了龙卷风上,而且轶事对它有所帮助。我的页面加载速度很慢,但通常情况下响应速度更快。另外,很有趣,但我似乎注意到,单独的Flask会随着时间的流逝而变慢,但是Flask + Tornado的速度会变慢。我想使用Apachemod_wsgi会使情况变得更好,但是Tornado的设置非常简单(请参见http://flask.pocoo.org/docs/deploying/others/)。

(还有一个相关的问题:Flask应用程序偶尔会挂起


0

我在这里有一个不同的解决方案。我只是.pyc从服务器目录中删除了所有文件,然后重新启动了它。顺便说一句,本地主机已经在我的主机文件(Windows 8)中被注释掉了。

服务器一直处于冻结状态,现在又可以正常工作了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.