2016-01-22 87 views
-1

我想知道是否可以使用Flask的concurrent.futures。这是一个例子。我会得到性能提升结合使用Flask的concurrent.futures

import requests 
from flask import Flask 
from concurrent.futures import ThreadPoolExecutor 

executor = ThreadPoolExecutor(max_workers=10) 
app = Flask(__name__) 

@app.route("/path/<xxx>") 
def hello(xxx): 
    f = executor.submit(task, xxx) 
    return "OK" 

def task(): 
    resp = requests.get("some_url") 
    # save to mongodb 

app.run() 

该任务是IO绑定的,不需要返回值。请求不会经常出现,我想最多是10个/秒。

我测试了它,它工作。我想知道的是,我是否可以通过这种方式使用多线程来获得性能提升。 Will Flask会以某种方式阻止任务?

+0

如果有不频繁I/O密集型的要求,你可能会更好使用与反应器模式行龙卷风网络服务器或类似图书馆扭曲。这不是烧瓶的典型用例。 – lc2817

+0

这似乎微不足道来验证。你是否在一个线程中运行了一个长时间的任务,并观察瓶口响应被阻止?如果没有,没有。你有什么实际问题? – davidism

+0

我试图做出决定,如果我应该使用它。 – laike9m

回答

4

这取决于比Flask更多的因素,就像你在Flask(gunicorn,gevent,uwsgi,nginx等)前面使用的一样。如果你发现你的“some_url”请求确实是一个瓶颈,把它推到另一个线程可能会提供一个提升,但这又取决于你的个人情况;网络堆栈中的许多元素都可以使流程“缓慢”。

而不是在Flask进程上多线程(可能会很快变得复杂),将I/O阻塞到辅助进程可能是更好的解决方案。您可以将Redis消息发送到在asyncio事件循环上运行的进程,该进程可以很好地进行扩展。

app.py

from flask import Flask 
import redis 

r = redis.StrictRedis(host='127.0.0.1', port=6379) 
app = Flask(__name__) 

@app.route("/") 
def hello(): 
    # send your message to the other process with redis 
    r.publish('some-channel', 'some data') 
    return "OK" 

if __name__ == '__main__': 
    app.run(port=4000, debug=True) 

helper.py

import asyncio 
import asyncio_redis 
import aiohttp 

@asyncio.coroutine 
def get_page(): 
    # get some url 
    req = yield from aiohttp.get('http://example.com') 
    data = yield from req.read() 

    # insert into mongo using Motor or some other async DBAPI 
    #yield from insert_into_database(data) 

@asyncio.coroutine 
def run(): 
    # Create connection 
    connection = yield from asyncio_redis.Connection.create(host='127.0.0.1', port=6379) 

    # Create subscriber. 
    subscriber = yield from connection.start_subscribe() 

    # Subscribe to channel. 
    yield from subscriber.subscribe([ 'some-channel' ]) 

    # Inside a while loop, wait for incoming events. 
    while True: 
     reply = yield from subscriber.next_published() 
     print('Received: ', repr(reply.value), 'on channel', reply.channel) 
     yield from get_page() 

    # When finished, close the connection. 
    connection.close() 

if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(run()) 
相关问题