Python 性能:异步请求处理程序,具有由工作池处理的阻塞任务

Python 性能:异步请求处理程序,具有由工作池处理的阻塞任务,python,asynchronous,tornado,Python,Asynchronous,Tornado,这个脚本的性能如何:复制如下 from time import sleep from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from tornado.web import Application, asynchronous, RequestHandler from multiprocessing.pool import ThreadPool _workers = ThreadPool(10)

这个脚本的性能如何:复制如下

from time import sleep
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application, asynchronous, RequestHandler
from multiprocessing.pool import ThreadPool

_workers = ThreadPool(10)

def run_background(func, callback, args=(), kwds={}):
    def _callback(result):
        IOLoop.instance().add_callback(lambda: callback(result))
    _workers.apply_async(func, args, kwds, _callback)

# blocking task like querying to MySQL
def blocking_task(n):
    sleep(n)
    return n

class Handler(RequestHandler):
    @asynchronous
    def get(self):
        run_background(blocking_task, self.on_complete, (10,))

    def on_complete(self, res):
        self.write("Test {0}<br/>".format(res))
        self.finish()

HTTPServer(Application([("/", Handler)],debug=True)).listen(8888)
IOLoop.instance().start()
从时间导入睡眠
从tornado.httpserver导入httpserver
从tornado.ioloop导入ioloop
从tornado.web导入应用程序,异步,RequestHandler
从multiprocessing.pool导入线程池
_工人=线程池(10)
def run_background(func,回调,args=(),kwds={}):
def_回调(结果):
IOLoop.instance().add_回调(lambda:callback(result))
_workers.apply\u async(func、args、kwds、\u回调)
#阻止像查询MySQL这样的任务
def阻塞_任务(n):
睡眠(n)
返回n
类处理程序(RequestHandler):
@异步的
def get(自我):
运行\u后台(阻塞\u任务,自启动\u完成,(10,))
def on_完成(自身、res):
self.write(“测试{0}
”。格式(res)) self.finish() HTTPServer(应用程序([(“/”,处理程序)],调试=True))。侦听(8888) IOLoop.instance().start()
  • 我的申请将远远超过1000个请求/秒
  • 每个请求将持续2-30秒,平均约6秒
    • 简单平均睡眠时间(6)
  • 通过使用类似于
    redis BLPOP
    Queue.get\u nowait()

  • 总体模式很好,但需要注意的是,由于GIL,线程池只能使用一个CPU,并且需要使用多个进程来充分利用可用的硬件


    仔细看看这些数字,如果您的请求平均每6秒,那么10个线程就太小了。每秒有6000秒的工作量,因此在所有进程中总共需要至少6000个线程(假设这6秒实际上只是阻塞外部事件,python进程的CPU成本可以忽略不计)。我不确定一个现代系统能处理多少线程,但6000个Python线程听起来不是一个好主意。如果每个请求都有6秒的阻塞时间(以及每秒数千个请求),那么将这些阻塞功能转换为异步似乎是值得的。

    您的任务是否需要CPU密集型?如果是这样,您可能希望将其分布在多个CPU上。但要做到这一点,您需要使用Python的另一个实现,它没有像Jython或IronPython那样的GIL。我已经更新了代码以反映您提出的问题。仍在工作中。。。但我的技术正在改进。谢谢你的建议,本!