Tornado同步的执行的代码变成异步

Tornado是一个异步非堵塞的web框架

但是在遇到数据库的io操作就会发现数据库的io操作是同步执行的

这样将会导致tornado的异步性能急剧下降

经过一系列搜索发现有两种方法可以使这个同步执行变成异步

方法一:使用线程

tornado中有个这样的装饰器run_on_executor

直接翻译过来就是运行在一个执行者上

那么这个执行者是谁呢?答案就是线程

from tornado import httpserver, ioloop
from tornado.web import RequestHandler, Application
from tornado.options import define, options
from tornado.concurrent import run_on_executor
import tornado.options
from concurrent.futures import ThreadPoolExecutor
import time

define('port', default=8000, type=int)


class SleepHandler(RequestHandler):
    # 设置线程的并发数量
    executor = ThreadPoolExecutor(max_workers=2)

    @run_on_executor
    def run_sleep(self):
        time.sleep(5)
        print('finish')
        return 10

    def get(self, *args, **kwargs):
        result = self.run_sleep()
        print(result)

        self.write('done')


if __name__ == '__main__':
    # 注意解析命令行一定要放在最前面执行
    tornado.options.parse_command_line()

    app = Application([
        (r'/sleep', SleepHandler),
    ])

    http_server = httpserver.HTTPServer(app)
    http_server.listen(options.port)
    ioloop.IOLoop.current().start()

# 执行结果:当调用run_sleep方法的时候,程序并没有等待结果完成,直接执行下面的代码
# 输出一下run_sleep返回结果会发现是一个<Future pending>

通过上面的程序会发现没办法获取到run_sleep的返回结果,可以使用gen.coroutine的方式来的到返回结果

from tornado import httpserver, ioloop, gen
from tornado.web import RequestHandler, Application
from tornado.options import define, options
from tornado.concurrent import run_on_executor
import tornado.options
from concurrent.futures import ThreadPoolExecutor
import time

define('port', default=8000, type=int)


class SleepHandler(RequestHandler):
    # 设置线程的并发数量
    executor = ThreadPoolExecutor(max_workers=2)

    @run_on_executor
    def run_sleep(self):
        time.sleep(5)
        print('finish')
        return 10

    @gen.coroutine
    def get(self, *args, **kwargs):
        result = yield self.run_sleep()
        self.write(str(result))
        self.write('done')

class Indexhandler(RequestHandler):
    def get(self, *args, **kwargs):
        self.write('index')
if __name__ == '__main__':
    # 注意解析命令行一定要放在最前面执行
    tornado.options.parse_command_line()

    app = Application([
        (r'/sleep', SleepHandler),
        (r'/index',Indexhandler)
    ])

    http_server = httpserver.HTTPServer(app)
    http_server.listen(options.port)
    ioloop.IOLoop.current().start()

方法二:通过进程的方式

from tornado import httpserver, ioloop, gen
from tornado.web import RequestHandler, Application
from tornado.options import define, options
import tornado.options

from concurrent.futures import ProcessPoolExecutor
import time

define('port', default=8000, type=int)
# 并发进程数
executor = ProcessPoolExecutor(max_workers=2)


def run_sleep():
    time.sleep(5)
    return 'sleep_done'


class SleepHandler(RequestHandler):

    # @gen.coroutine
    def get(self, *args, **kwargs):
        #把要执行的函数提交到进程中
        executor.submit(run_sleep)
        


if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = Application([
        (r'/sleep', SleepHandler)
    ])
    http_server = httpserver.HTTPServer(app)
    http_server.listen(options.port)
    ioloop.IOLoop.current().start()

获取异步执行的结果与方法一相同,使用gen.coroutine

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值