Tornado 多進程 & 異步

另一篇:http://www.cnblogs.com/xiaoshi657/p/6945208.htmlhtml

基本版:

#coding=utf-8

import tornado.web
import tornado.httpserver
import tornado.options
import tornado.ioloop

from tornado.options import options , define
define("port",default=8001,help="跑在8001",type=int)

import time
class SleepHandler(tornado.web.RequestHandler):
    def get(self):
        time.sleep(5)
        self.write("this is SleepHandler...")

class DirectHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("this is DirectHandler...")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers = [
            (r"/d",DirectHandler),
            (r"/s",SleepHandler),
        ],
        debug = True
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

多進程版本

注意必定要關閉debug功能!!!不然:Cannot run in multiple processes: IOLoop instancepython

#coding:utf-8

import tornado.web
import tornado.httpserver
import tornado.options
import tornado.ioloop

from tornado.options import options , define
define("port",default=8001,help="跑在8001",type=int)

import time
class SleepHandler(tornado.web.RequestHandler):
    def get(self):
        time.sleep(10)
        self.write("this is SleepHandler...")

class DirectHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("this is DirectHandler...")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers = [
            (r"/d",DirectHandler),
            (r"/s",SleepHandler),
        ],
        debug = False
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.bind(options.port)
    http_server.start(0)
    # [I 150610 10:42:05 process:115] Starting 4 processes
    tornado.ioloop.IOLoop.instance().start()

bind文檔翻譯

def bind(self, port, address=None, family=socket.AF_UNSPEC, backlog=128):
    """ 綁定server到指定地址的端口上。 調用start來啓動server。若是想把這個server跑在單線程上,能夠調用listen方法,listen是bind和start方法的單進程模式的「快捷鍵」。 地址多是ip地址或者hostname。若是是hostname,server將監聽其全部關聯ip。 地址如果空字符串將監聽不到任何可用接口。family參數可設置爲socket.AF_INET或socket.AF_INET6來約定ipv4或者是ipv6地址,缺省狀況下會啓用全部可用的。 backlog參數與socket.listen同義。 bind方法會屢次在start方法前調用來監聽多個端口或者接口。 """
    sockets = bind_sockets(port, address=address, family=family,
                           backlog=backlog)
    if self._started:
        self.add_sockets(sockets)
    else:
        self._pending_sockets.extend(sockets)

start文檔翻譯

def start(self, num_processes=1):
    """ 默認狀況下,但進程運行server,不會fork任何額外的子進程。 若是num_processes爲None或<=0 ,會根據機器的cpu核數fork子進程。若num_processes>=1,就fork這個數目的子進程。 由於咱們使用的是進程而不是線程,因此不會在server code之間共享內存。 特別注意,多進程與自動裝載模型不兼容。在調用TCPServer.start(n)前,任何IOLoop都不能建立和引用。 """
    assert not self._started
    self._started = True
    if num_processes != 1:
        process.fork_processes(num_processes)
    sockets = self._pending_sockets
    self._pending_sockets = []
    self.add_sockets(sockets)

異步版本1

#coding:utf-8

import tornado.web
import tornado.httpserver
import tornado.options
import tornado.ioloop

from tornado.options import options , define
define("port",default=8001,help="跑在8001",type=int)

import time
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("this is SleepHandler...")
        self.finish()


class DirectHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("this is DirectHandler...")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers = [
            (r"/d",DirectHandler),
            (r"/s",SleepHandler),
        ],
        debug = False
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.bind(options.port)
    http_server.start(1)
    tornado.ioloop.IOLoop.instance().start()

將sleep.py的代碼如上述同樣改造,即在get()方法前面增長了裝飾器@tornado.web.asynchronous,它的做用在於將tornado服務器自己默認的設置_auto_fininsh值修改成false。若是不用這個裝飾器,客戶端訪問服務器的get()方法並獲得返回值以後,兩隻之間的鏈接就斷開了,可是用了@tornado.web.asynchronous以後,這個鏈接就不關閉,直到執行了self.finish()才關閉這個鏈接。git

tornado.ioloop.IOLoop.instance().add_timeout()也是一個實現異步的函數,time.time()+17是給前面函數提供一個參數,這樣實現了至關於time.sleep(17)的功能,不過,尚未完成,當這個操做完成以後,就執行回調函數on_response()中的self.render(「sleep.html」),並關閉鏈接self.finish()。 
https://github.com/qiwsir/StarterLearningPython/blob/master/309.mdgithub

異步版本二

#coding:utf-8

import tornado.web
import tornado.httpserver
import tornado.options
import tornado.ioloop
import tornado.gen

from tornado.options import options , define
define("port",default=8001,help="跑在8001",type=int)

import time
class SleepHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        #使用yield獲得了一個生成器,先把流程掛起,等徹底完畢,再喚醒繼續執行。另,生成器都是異步的。
        yield tornado.gen.Task(tornado.ioloop.IOLoop.instance().add_timeout, time.time() + 5)
        self.write("this is SleepHandler...")


class DirectHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("this is DirectHandler...")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers = [
            (r"/d",DirectHandler),
            (r"/s",SleepHandler),
        ],
        debug = False
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.bind(options.port)
    http_server.start(1)
    tornado.ioloop.IOLoop.instance().start()

轉自:https://blog.csdn.net/yongche_shi/article/details/53694145
相關文章
相關標籤/搜索