<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        tornado異步請求非阻塞

        來源:懂視網 責編:小采 時間:2020-11-27 14:28:45
        文檔

        tornado異步請求非阻塞

        tornado異步請求非阻塞:前言也許有同學很迷惑:tornado不是標榜異步非阻塞解決10K問題的嘛但是我卻發現不是torando不好,而是你用錯了.比如最近發現一個事情:某網站打開頁面很慢,服務器cpu/內存都正常.網絡狀態也良好. 后來發現,打開頁面會有很多請求后端數據庫的訪問,有一個mo
        推薦度:
        導讀tornado異步請求非阻塞:前言也許有同學很迷惑:tornado不是標榜異步非阻塞解決10K問題的嘛但是我卻發現不是torando不好,而是你用錯了.比如最近發現一個事情:某網站打開頁面很慢,服務器cpu/內存都正常.網絡狀態也良好. 后來發現,打開頁面會有很多請求后端數據庫的訪問,有一個mo

        前言

        也許有同學很迷惑:tornado不是標榜異步非阻塞解決10K問題的嘛?但是我卻發現不是torando不好,而是你用錯了.比如最近發現一個事情:某網站打開頁面很慢,服務器cpu/內存都正常.網絡狀態也良好. 后來發現,打開頁面會有很多請求后端數據庫的訪問,有一個mongodb的數據庫業務api的rest服務.但是它的tornado卻用錯了,一步步的來研究問題:

        說明

        以下的例子都有2個url,一個是耗時的請求,一個是可以或者說需要立刻返回的請求,我想就算一個對技術不熟,從道理上來說的用戶, 他希望的是他訪問的請求不會影響也不會被其他人的請求影響

        #!/bin/env python

        import tornado.httpserver

        import tornado.ioloop

        import tornado.options

        import tornado.web

        import tornado.httpclient

        import time

        from tornado.options import define, options

        define("port", default=8000, help="run on the given port", type=int)

        class SleepHandler(tornado.web.RequestHandler):

        def get(self):

        time.sleep(5)

        self.write("when i sleep 5s")

        class JustNowHandler(tornado.web.RequestHandler):

        def get(self):

        self.write("i hope just now see you")

        if __name__ == "__main__":

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[

        (r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])

        http_server = tornado.httpserver.HTTPServer(app)

        http_server.listen(options.port)

        tornado.ioloop.IOLoop.instance().start()

        假如你使用頁面請求或者使用哪個httpie,curl等工具先訪問http://localhost:8000/sleep,再訪問http://localhost:8000/justnow.你會發現本來可以立刻返回的/jsutnow的請求會一直阻塞到/sleep請求完才返回.

        這是為啥?為啥我的請求被/sleep請求阻塞了?如果平時我們的web請求足夠快我們可能不會意識到這個問題,但是事實上經常會有一些耗時的進程,意味著應用程序被有效的鎖定直至處理結束.

        這是時候你有沒有想起@tornado.web.asynchronous這個裝飾器?但是使用這個裝飾器有個前提就是你要耗時的執行需要執行異步,比如上面的time.sleep,你只是加裝飾器是沒有作用的,而且需要注意的是 Tornado默認在函數處理返回時關閉客戶端的連接,但是當你使用@tornado.web.asynchonous裝飾器時,Tornado永遠不會自己關閉連接,需要顯式的self.finish()關閉

        我們大部分的函數都是阻塞的, 比如上面的time.sleep其實tornado有個異步的實現:

        #!/bin/env python

        import tornado.httpserver

        import tornado.ioloop

        import tornado.options

        import tornado.web

        import tornado.gen

        import tornado.httpclient

        import tornado.concurrent

        import tornado.ioloop

        import time

        from tornado.options import define, options

        define("port", default=8000, help="run on the given port", type=int)

        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("when i sleep 5s")

        class JustNowHandler(tornado.web.RequestHandler):

        def get(self):

        self.write("i hope just now see you")

        if __name__ == "__main__":

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[

        (r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])

        http_server = tornado.httpserver.HTTPServer(app)

        http_server.listen(options.port)

        tornado.ioloop.IOLoop.instance().start()

        這里有個新的tornado.gen.coroutine裝飾器, coroutine是3.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("when i sleep 5s")

        self.finish()

        使用了callback, 但是新的裝飾器讓我們通過yield實現同樣的效果:你在打開/sleep之后再點擊/justnow, justnow的請求都是立刻返回不受影響.但是用了asynchronous的裝飾器你的耗時的函數也需要執行異步

        剛才說的都是沒有意義的例子,下面寫個有點用的:讀取mongodb數據庫數據,然后再前端按行write出來

        #!/bin/env python

        import tornado.httpserver

        import tornado.ioloop

        import tornado.options

        import tornado.web

        import tornado.gen

        import tornado.httpclient

        import tornado.concurrent

        import tornado.ioloop

        import time

        # 一個mongodb出品的支持異步的數據庫的python驅動

        import motor

        from tornado.options import define, options

        define("port", default=8000, help="run on the given port", type=int)

        # db其實就是test數據庫的游標

        db = motor.MotorClient().open_sync().test

        class SleepHandler(BaseHandler):

        @tornado.web.asynchronous

        @tornado.gen.coroutine

        def get(self):

        # 這一行執行還是阻塞需要時間的,我的tt集合有一些數據并且沒有索引

        cursor = db.tt.find().sort([('a', -1)])

        # 這部分會異步非阻塞的執行二不影響其他頁面請求

        while (yield cursor.fetch_next):

        message = cursor.next_object()

        self.write('

      1. %s
      2. ' % message['a'])

        self.write('')

        self.finish()

        def _on_response(self, message, error):

        if error:

        raise tornado.web.HTTPError(500, error)

        elif message:

        for i in message:

        self.write('

      3. %s
      4. ' % i['a'])

        else:

        self.write('')

        self.finish()

        class JustNowHandler(BaseHandler):

        def get(self):

        self.write("i hope just now see you")

        if __name__ == "__main__":

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[

        (r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])

        http_server = tornado.httpserver.HTTPServer(app)

        http_server.listen(options.port)

        tornado.ioloop.IOLoop.instance().start()

        一個同事提示為什么這個耗時的東西不能異步的丟給某工具去執行而不阻塞我的請求呢?好吧,我也想到了:celery,正好github有這個東西:tornado-celery

        執行下面的程序首先你要安裝rabbitmq和celery:

        #!/bin/env python

        import tornado.httpserver

        import tornado.ioloop

        import tornado.options

        import tornado.web

        import tornado.gen

        import tornado.httpclient

        import tcelery, tasks

        import time

        from tornado.options import define, options

        define("port", default=8000, help="run on the given port", type=int)

        tcelery.setup_nonblocking_producer()

        class SleepHandler(tornado.web.RequestHandler):

        @tornado.web.asynchronous

        @tornado.gen.coroutine

        def get(self):

        # tornado.gen.Task的參數是:要執行的函數, 參數

        yield tornado.gen.Task(tasks.sleep.apply_async, args=[5])

        self.write("when i sleep 5s")

        self.finish()

        class JustNowHandler(tornado.web.RequestHandler):

        def get(self):

        self.write("i hope just now see you")

        if __name__ == "__main__":

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[

        (r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])

        http_server = tornado.httpserver.HTTPServer(app)

        http_server.listen(options.port)

        tornado.ioloop.IOLoop.instance().start()

        task是celery的任務定義的文件,包含我們說的time.sleep的函數

        import time

        from celery import Celery

        celery = Celery("tasks", broker="amqp://guest:guest@localhost:5672")

        celery.conf.CELERY_RESULT_BACKEND = "amqp"

        @celery.task

        def sleep(seconds):

        time.sleep(float(seconds))

        return seconds

        if __name__ == "__main__":

        celery.start()

        然后啟動celelry worker(要不然你的任務怎么執行呢?肯定需要一個消費者取走):

        celery -A tasks worker --loglevel=info

        但是這里的問題也可能很嚴重:我們的異步非阻塞依賴于celery,還是這個隊列的長度,假如任務很多那么就需要等待,效率很低.有沒有一種辦法把我的同步阻塞函數變為異步(或者說被tornado的裝飾器理解和識別)呢?

        #!/bin/env python

        import tornado.httpserver

        import tornado.ioloop

        import tornado.options

        import tornado.web

        import tornado.httpclient

        import tornado.gen

        from tornado.concurrent import run_on_executor

        # 這個并發庫在python3自帶在python2需要安裝sudo pip install futures

        from concurrent.futures import ThreadPoolExecutor

        import time

        from tornado.options import define, options

        define("port", default=8000, help="run on the given port", type=int)

        class SleepHandler(tornado.web.RequestHandler):

        executor = ThreadPoolExecutor(2)

          #executor 是局部變量 不是全局的

        @tornado.web.asynchronous

        @tornado.gen.coroutine

        def get(self):

        # 假如你執行的異步會返回值被繼續調用可以這樣(只是為了演示),否則直接yield就行

        res = yield self.sleep()

        self.write("when i sleep %s s" % res)

        self.finish()

        @run_on_executor

        def sleep(self):

        time.sleep(5)

        return 5

        class JustNowHandler(tornado.web.RequestHandler):

        def get(self):

        self.write("i hope just now see you")

        if __name__ == "__main__":

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[

        (r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])

        http_server = tornado.httpserver.HTTPServer(app)

        http_server.listen(options.port)

        tornado.ioloop.IOLoop.instance().start()

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        tornado異步請求非阻塞

        tornado異步請求非阻塞:前言也許有同學很迷惑:tornado不是標榜異步非阻塞解決10K問題的嘛但是我卻發現不是torando不好,而是你用錯了.比如最近發現一個事情:某網站打開頁面很慢,服務器cpu/內存都正常.網絡狀態也良好. 后來發現,打開頁面會有很多請求后端數據庫的訪問,有一個mo
        推薦度:
        標簽: 請求 調用 異步
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 久久国产亚洲高清观看| 国产91在线免费| 亚洲精品乱码久久久久久中文字幕| 亚洲av无码一区二区三区四区 | 亚洲 欧洲 日韩 综合在线| 国产妇乱子伦视频免费| 亚洲大香人伊一本线| 麻豆国产入口在线观看免费| 亚洲一卡二卡三卡| 日韩精品福利片午夜免费观着| 亚洲av日韩av欧v在线天堂| 爱爱帝国亚洲一区二区三区| 国产精品免费一级在线观看| 国产亚洲精品免费| 久久久久一级精品亚洲国产成人综合AV区 | 亚洲人午夜射精精品日韩| 亚洲性天天干天天摸| 中文字幕亚洲免费无线观看日本| 2022年亚洲午夜一区二区福利| 亚洲综合免费视频| 亚洲欧美日韩中文字幕一区二区三区| 国产精品无码一二区免费| 人碰人碰人成人免费视频| 国产AV无码专区亚洲AV男同| 美女内射无套日韩免费播放 | 美女网站在线观看视频免费的| 亚洲va无码手机在线电影| 日本视频一区在线观看免费| 亚洲熟妇无码AV| 亚洲国产激情一区二区三区| 暖暖在线视频免费视频| 亚洲国产精品专区| 亚洲av片一区二区三区| 亚洲视频在线免费观看| 亚洲欧好州第一的日产suv| 亚洲无码视频在线| 99在线精品免费视频九九视| 国产精品亚洲精品爽爽| 午夜影视日本亚洲欧洲精品一区| 岛国av无码免费无禁网站| eeuss免费天堂影院|