快捷搜索:  xmind  endnote  clip  mplus  prism  idea  pycharm  csp

tornado代码实现python后端异步接口

tornado是一个异步非阻塞框架,对于高并发情况非常友好,本文教大家怎么实现tornado的异步,提升自己服务接口的吞吐率!

大多数新手可能对异步非阻塞不是很理解,现在详细讲解:

  1. 假设你的后端程序是单进程运行的,有两个用户同时请求,如果你处理a用户的事务时间比较长,那么b用户就得一直等待a用户处理完事务才能响应b用户。
  2. 出现上述情况通常是阻塞型任务,比如:数据库操作、复杂的计算、网络请求等

为了解决上述的问题,tornado框架自带协程的方法进行处理阻塞的事务

关于使用延迟函数

以下1和2采用协程的方式(@tornado.gen.coroutin),3采用回调函数的方式

  1. 如果tornado版本在4.1之后,不能使用time.sleep(),而是yield tornado.gen.sleep(),因为如果方法装饰协程的话,阻塞的事务调用也必须是协程的方式,所以不能用time.sleep()
class TestHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        print('test')
        yield gen.sleep(10)
        self.write("sleep 10s")
  1. 如果tornado版本在3.0 ~ 4.1间,可以使用yield tornado.gen.Task(tornado.ioloop.IOLoop.instance().add_timeout, time.time() + 10)
class SleepHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self):
        yield tornado.gen.Task(tornado.ioloop.IOLoop.instance().add_timeout, time.time() + 5)
        self.write("sleep 10s")

  1. 如果tornado版本在3.0前,使用callback方式,非协程
# tornado3.0之前
class SleepHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 5, callback=self.on_response)
    def on_response(self):
        self.write("sleep 5s")
        self.finish()

上述如果用浏览器测试相同的接口的话还是会出现等待A完成后再处理B的情况,这是因为浏览器的缘故,请求接口的时候加上不同的参数即可,如带上当前时间戳&_t=1354545680526

关于阻塞型事务

  • 前面说过,用协程的方式的话,阻塞的语句需要使用阻塞库来操作,能不能使用常用的写法,答案是可以的,即通过线程的方式。
  • 下述demo中,一共分为三步,1. 为这接口定义线程池的大小 2. 阻塞的事务函数加上@run_on_executor装饰器 3. 网络函数使用协程处理
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor

class LogHandler(tornado.web.RequestHandler):
    # 1.线程池大小
    executor = ThreadPoolExecutor(4)

    # 2.阻塞的函数上加@run_on_executor
    @run_on_executor
    def sleep(self, second):
        time.sleep(second)
        return second

    @gen.coroutine
    def get(self):
        # 3.yield来调用 # (没有返回也要yield)
        second = yield self.sleep(10)
        self.write('noBlocking Request: {}'.format(second))
      

关于tornado高并发的内容会持续在此文更新,接下来会添加网络io的处理!!!

您可能还会对下面的文章感兴趣: