3

基本的な考え方は次のとおりです。

リクエストが来てviews1、最初にユーザー名を返します。do_something_elseviews1が完了した直後に、いくつかの重い仕事が分離されています。これは新しいユーザーの作成と考えることができますが、バックグラウンドでかなりのチェックを行う必要があります。

def views1(..):
   username = get_uername(...)
   return username

from lib import do_something_else
def do_something_else(...):
   // do heavy stuff here

gevent.joinall([
   gevent.spawn(views1, parmeter1, parmeter2, ...),
   gevent.spawn(do_something_else, parmeter1, parmeter2, ...)
])

do_something_else問題は、ログに基づいて呼び出されたとは思わないことです。チュートリアルを読みましたが、どこに配置すればよいかわかりませんgevent.sleep(0)。ブロックしたくない。ユーザーにユーザー名をすぐに見てもらいdo_something_else、バックグラウンドで実行させます。

何か案が?

4

1 に答える 1

3

「負荷の高い」処理をスレッド プールに分離する必要があることを理解することが重要です [1]。

gevent スレッドで行われるすべての処理 (ネイティブ スレッドごとに 1 つの gevent HUB を持つことができます) は、ネットワーク リクエストの処理と応答の送信だけに集中する必要があります。

from gevent import spawn, run
from gevent.threadpool import ThreadPool
from time import sleep as heavy_load, time as now

class Globals:
    jobs = 4
    index = 0
    greenlets = []
    pool = ThreadPool(3) # change size of the pool appropriately

start = now()

def get_uername():
    heavy_load(0.1)
    Globals.index += 1
    return "Alex {0}".format(Globals.index)

def do_something_else(username):
    heavy_load(2.0)
    print "Heavy job done for", username, now() - start

def views1():
    "a request comes to views1 and it first returns the username"
    username = get_uername()
    ## There is some heavy job separate done by do_something_else right after views1 is done
    Globals.greenlets.append( 
        Globals.pool.spawn(do_something_else, username) 
        )
    # return username
    print "Returned requested username", username, now() - start


if __name__ == '__main__':
    ## simulate clients 
    for job_index in xrange(Globals.jobs):
        Globals.greenlets.append( spawn(views1) )

    ## wait for all tasks to complete
    # for greenlet in Globals.greenlets:
        # try:
            # greenlet.join()
        # except AttributeError, e:
            # greenlet.get()
    run()
    print "Test done", now() - start

これはテストの出力です:

python threadpool_test.py
Returned requested username Alex 1 0.101000070572
Returned requested username Alex 2 0.201999902725
Returned requested username Alex 3 0.302999973297
Returned requested username Alex 4 0.40299987793
Heavy job done for Alex 1 2.10100007057
Heavy job done for Alex 2 2.2009999752
Heavy job done for Alex 3 2.3029999733
Heavy job done for Alex 4 4.10299992561
Test done 4.10500001907

すべてのリクエストが最初に完了し、並列do_something_elseタスクがサイズ 3 のバッチでどのように実行されるかに注目してください。

ThreadPool が使用されていない場合、すべてのリクエストには追加の時間がかかりますが、これは gevent が提供するものdo_something_elseではありません。asynchronous programmingその場合、出力は次のようになります。

Heavy job done for Alex 1 2.10100007057
Returned requested username Alex 1 2.10100007057
Heavy job done for Alex 2 4.2009999752
Returned requested username Alex 2 4.20199990273
Heavy job done for Alex 3 6.30200004578
Returned requested username Alex 3 6.3029999733
Heavy job done for Alex 4 8.40299987793
Returned requested username Alex 4 8.40400004387
Test done 8.40400004387

非同期で処理された場合、4 番目の要求が 0.4 秒ではなく 8.4 秒で完了したことに注意してください。

[1] http://code.google.com/p/gevent/source/browse/examples/threadpool.py

于 2012-07-23T10:16:11.477 に答える