前書き
おそらく一部の学生は混乱しているでしょう: torando は 10K 問題を解決するために非同期でノンブロッキングであると主張していますか? しかし、私は torando が悪いということではなく、それを間違って使用していることに気付きました。 、最近発見したのは、Web サイトのページを開くのが非常に遅い、サーバーの CPU/メモリは正常である、後でページを開くと背面へのアクセス要求が多数あることがわかりました。 -end データベース mongodb データベース ビジネス API の休息サービスがありますが、その竜巻は間違って使用されています。問題を段階的に見てみましょう:
class JustNowHandler(tornado.web.RequestHandler): def get(self): self.write( "今会えるといいな")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 リクエストが完了するまでブロックされてから返されます
Import Tornado.Web 、デフォルト = 8000、ヘルプ = "指定されたポートで実行"、タイプ = 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 (Tor nado.web .RequestHandler):
def get(self):
self.write("今会えることを願っています")
if __name__ == "__main__":
tornado.options.parse_command_line( )app = tornado.web.application(handlers = [
)option.port)
tornado.ioloop.ioloop.instance()は 3.0 以降の新しいデコレータです。以前のメソッドは callbacks を使用するか、私の例を見てください:
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("5秒寝たとき" ) self.finish()コールバックが使用されていますが、新しいデコレータを使用すると、yield を通じて同じ効果を実現できます。/sleep を開いてから /justnow をクリックすると、justnow リクエストは影響を受けずにすぐに返されます。ただし、非同期デコレータを使用すると、時間がかかります。関数も非同期で実行する必要があります
私が今挙げた例はすべて無意味な例です。これは便利な例です。mongodb データベースのデータを読み取り、それをフロントエンドで 1 行ずつ書き出します
#! /bin/env python
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.gen
import tornado.httpclient
importトルネード.コンカレント
import tornado.ioloop
import time
# 非同期データベースをサポートするmongodbによって生成されたPythonドライバー
import motor
from tornado.options import define, options
define("port",default=8000, help =" 指定されたポートで実行します", type=int)
# db は実際にはテスト データベースのカーソルです
db =motor.MotorClient().open_sync().test
class SleepHandler(BaseHandler):
@tornado.web .asynchronous
@tornado.gen.coroutine
def get(self):
# 私の tt コレクションにはいくつかのデータがあり、インデックス
カーソル = db がありません。 tt.find( ) .sort ([('a', -1)])
# この部分は非同期で非ブロッキングになります。 : : エラーの場合: raise tornado.web.httperror (500, error) )elifメッセージ:self.self.write( '
%s'%i ['a'])
if __name__ == "__main__": tornado.options.parse_command_line()http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
同僚が、なぜ「できない」と提案しましたこの時間のかかるものを、リクエストをブロックせずに実行するためにツールに非同期的にスローすることはできますか? Rabbitmq と celery をインストールするには:
#!/bin/env pythonimport tornado.httpserverimport tornado.gen
import tornado.httpclient
import tcelery、tasks
import time
from tornado.options import define、options
define("port", default=8000, help="指定されたポートで実行", type= int)
tcelery.setup_nonblocking_Producer()
class SleepHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.coroutine
def get(self):
# tornado Gen.タスクのパラメータは: 実行される関数、パラメータ
yield tornado.gen.task (tasks.sleep.apply_async, args = [5])
Self.write ("When I Sleep 5s")
def get(self):
self.write("今会いましょう")
if __name__ == "__main__":
tornado .options.parse_command_line()
app = tornado.web.Application(handlers=[
(r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])
http_server = httpserver。 HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
task は、私たちが話している time.sleep を含む celery のタスク定義ファイルです。
輸入時間セロリの輸入からcelery = Celery("タスク", Broker="amqp://guest:guest@localhost:5672")
celery.conf.CELERY_RESULT_BACKEND = "amqp"
@celery.task
def sleep(秒):
time.sleep(float(秒))
秒を返す
if __name__ == "__main__":
celery.start()
次に、celeryワーカーを開始します(そうでない場合、タスクはどのように実行されますか?は間違いなく必要です。消費者がそれを奪います):
celery -A タスクワーカー --loglevel=info
しかし、ここでの問題も深刻である可能性があります。非同期ノンブロッキングはセロリ、またはこの長さに依存します。キュー、タスクが多数ある場合、待機する必要がありますが、これは非常に非効率です。同期ブロック機能を非同期に変更する方法はありますか?
# !/bin/env python
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
import tornado.gen
from現在のインポート run_on_executor
# この同時実行ライブラリ python3 では、 sudo pip install futures をインストールする必要があります
from concurrent.futures import ThreadPoolExecutor
import time
from tornado.options import define, options
define("port",default=8000) , help="指定されたポートで実行します", 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() 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 wish 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()