搜尋
首頁後端開發Python教學tornado非同步請求非阻塞

前言

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


說明

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


#!/bin/env python

import tornado.http

import

import tornado.httpopin

import

import tornado.options

import tornado.web

import tornado.httpclient

import time

from tornado.options import defined given port", type=int)

class SleepHandler(tornado.web.RequestHandler):

    def get(self):

   ")

class JustNowHandler(tornado.web.RequestHandler):

    def get(self):

        self.write("i hope just now see you__ 🠎 ornado.options. parse_command_line()

    app = tornado.web.Application(handlers=[

            (r"/sleep", SleepHandler), (r"/justnow", J TPServer(app )

    http_server.listen(options.port)

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

假如你使用頁面請求或使用哪個工具先訪問http://localhost /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.iolooppopornp.

import tornado.gen

import tornado.httpclient

import tornado.concurrent

import tornado.ioloop

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

class SleepHandler(tornado.web.RequestHandler):

    @tornado.web.asynchronous

    @tornado.web.asynchronous

   

        yield tornado.gen.Task(tornado.ioloop.IOLoop.instance().add_timeout, time.time() + 5)

  sel    web .RequestHandler):

    def get(self):

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

if __name__ option;

    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

    @tornado.web.asynchronous

. .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。 rent

import tornado.ioloop

import time

# 一個mongodb出品的支援異步的資料庫的python驅動

import motor

from tornado.options import define, optorsdefine

from tornado.options defimport run on the given port", type=int)

# db其實就是test資料庫的遊標

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

class SleepHandler(BaseHandler): .asynchronous

    @tornado.gen.coroutine

    def get(self):

        # 這一行執行還是阻塞需要時間的,我的

        # 這一行執行還是阻塞需要時間的,我的

        # ) 。 _object( )

            self.write('

%s

' % message['a']))

     

    def _on_response(self, message, error):

        if error:

            raise tornado.web.HTTPError(500, error)

𠟎  for i in message:

                self.write('

%s

' % i['a'])

        else:

  •             self.write('')

        sel

        def get(self):

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

    if __name__ == "__main__":

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[Han (r"/真主這個耗時的東西不能異步的丟給某工具去執行而不阻塞我的請求呢?好吧,我也想到了: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

    int)

    tcelery.setup_nonblocking_producer()

    class SleepHandler(tornado.web.RequestHandler):

        @tornado.web.asynch :

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

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

    selfin    self .finish()


    class JustNowHandler(tornado.web.RequestHandler):

        def get(self):

           ==

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[

             http_server = tornado. httpserver.HTTPServer(app)

        http_server.listen(options.port)

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

    time

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

    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()

    Then start the celelry worker (otherwise, how will your task be executed? It is definitely needed A consumer takes it away):


    celery -A tasks worker --loglevel=info

    But the problem here may also be serious: our asynchronous non-blocking depends on celery, or the length of this queue, if the task If there are many, then you need to wait, which is very inefficient. Is there a way to change my synchronous blocking function to asynchronous (or be understood and recognized by tornado's decorator)?


    #!/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

    # This concurrency library In python3, you need to install 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 is a local variable not global

    @tornado.web.asynchronous

    @tornado.gen.coroutine

    def get(self):

    # If the asynchronous execution you perform will return a value and continue to be called, you can do this (just for demonstration), otherwise just yield directly

    res = yield self.sleep() I Self.write ("WHEN I SLEEP % 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()

  • 陳述
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    如何使用Python查找文本文件的ZIPF分佈如何使用Python查找文本文件的ZIPF分佈Mar 05, 2025 am 09:58 AM

    本教程演示如何使用Python處理Zipf定律這一統計概念,並展示Python在處理該定律時讀取和排序大型文本文件的效率。 您可能想知道Zipf分佈這個術語是什麼意思。要理解這個術語,我們首先需要定義Zipf定律。別擔心,我會盡量簡化說明。 Zipf定律 Zipf定律簡單來說就是:在一個大型自然語言語料庫中,最頻繁出現的詞的出現頻率大約是第二頻繁詞的兩倍,是第三頻繁詞的三倍,是第四頻繁詞的四倍,以此類推。 讓我們來看一個例子。如果您查看美國英語的Brown語料庫,您會注意到最頻繁出現的詞是“th

    我如何使用美麗的湯來解析HTML?我如何使用美麗的湯來解析HTML?Mar 10, 2025 pm 06:54 PM

    本文解釋瞭如何使用美麗的湯庫來解析html。 它詳細介紹了常見方法,例如find(),find_all(),select()和get_text(),以用於數據提取,處理不同的HTML結構和錯誤以及替代方案(SEL)

    python中的圖像過濾python中的圖像過濾Mar 03, 2025 am 09:44 AM

    處理嘈雜的圖像是一個常見的問題,尤其是手機或低分辨率攝像頭照片。 本教程使用OpenCV探索Python中的圖像過濾技術來解決此問題。 圖像過濾:功能強大的工具圖像過濾器

    如何使用Python使用PDF文檔如何使用Python使用PDF文檔Mar 02, 2025 am 09:54 AM

    PDF 文件因其跨平台兼容性而廣受歡迎,內容和佈局在不同操作系統、閱讀設備和軟件上保持一致。然而,與 Python 處理純文本文件不同,PDF 文件是二進製文件,結構更複雜,包含字體、顏色和圖像等元素。 幸運的是,借助 Python 的外部模塊,處理 PDF 文件並非難事。本文將使用 PyPDF2 模塊演示如何打開 PDF 文件、打印頁面和提取文本。關於 PDF 文件的創建和編輯,請參考我的另一篇教程。 準備工作 核心在於使用外部模塊 PyPDF2。首先,使用 pip 安裝它: pip 是 P

    如何在django應用程序中使用redis緩存如何在django應用程序中使用redis緩存Mar 02, 2025 am 10:10 AM

    本教程演示瞭如何利用Redis緩存以提高Python應用程序的性能,特別是在Django框架內。 我們將介紹REDIS安裝,Django配置和性能比較,以突出顯示BENE

    如何使用TensorFlow或Pytorch進行深度學習?如何使用TensorFlow或Pytorch進行深度學習?Mar 10, 2025 pm 06:52 PM

    本文比較了Tensorflow和Pytorch的深度學習。 它詳細介紹了所涉及的步驟:數據準備,模型構建,培訓,評估和部署。 框架之間的關鍵差異,特別是關於計算刻度的

    Python中的平行和並發編程簡介Python中的平行和並發編程簡介Mar 03, 2025 am 10:32 AM

    Python是數據科學和處理的最愛,為高性能計算提供了豐富的生態系統。但是,Python中的並行編程提出了獨特的挑戰。本教程探討了這些挑戰,重點是全球解釋

    如何在Python中實現自己的數據結構如何在Python中實現自己的數據結構Mar 03, 2025 am 09:28 AM

    本教程演示了在Python 3中創建自定義管道數據結構,利用類和操作員超載以增強功能。 管道的靈活性在於它能夠將一系列函數應用於數據集的能力,GE

    See all articles

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    2 週前By尊渡假赌尊渡假赌尊渡假赌
    倉庫:如何復興隊友
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    Hello Kitty Island冒險:如何獲得巨型種子
    4 週前By尊渡假赌尊渡假赌尊渡假赌

    熱工具

    MantisBT

    MantisBT

    Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    mPDF

    mPDF

    mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

    DVWA

    DVWA

    Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中