2012-07-21 26 views
3

基本思路如下:如何在第一個使用gevent完成後產生不同的功能?

請求來到views1,它首先返回用戶名。在視圖1完成之後,有一些繁重的工作由do_something_else單獨完成。您可以將其視爲創建新用戶,但必須對背景進行一些嚴格檢查。

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在後臺運行。

有什麼想法?

+0

重要的建議:採取一些額外的時間,使您的問題的獨立的測試,這將使問題清晰,你更專業。 – Alex 2012-07-23 10:17:45

回答

2

理解您需要將「重負載」處理分離到線程池[1]中很重要。

在gevent線程中發生的每個處理(並且每個本地線程都可以有一個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

當不使用線程池的大小批量完成每個請求需要額外的時間do_something_else引入,這不是asynchronous programming gevent必須提供。在這種情況下,輸出應該是這樣的:

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 

注意如何當異步處理的第四請求完成亞特8.4秒代替0.4秒。

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

+0

Fantasic。我將不得不嘗試明天實施這個。三個問題。一,「工作」究竟意味着什麼?請問進來的數量是多少(數字如何影響我的用法?)二,你能說出最後一點嗎?當ThreadPool ....'?你是否說我們不知道工作完成的時間,因爲沒有'job id'返回像任務隊列?這就是你的意思gevent沒有做愛嗎?我可能會誤解gevent提供的。謝謝 – user423455 2012-07-24 04:18:02

+0

作業意味着一些背景/並行處理器負擔重,作業== 4是請求的數量(也是do_something_else調用的數量)。我編輯了包含輸出的答案,以便在處理請求時錯誤地調用do_something_else()。你看到這會如何影響迴應? – Alex 2012-07-24 16:28:27

+0

啊。謝謝。很明顯。現在,最重要的問題......它可能是愚蠢的,但我究竟在哪兒放了'greenlets.append(spawn(view1))'?我使用Pylon和Django。他們都是與gunicorn服役。這是我不太明白的地方......我究竟在哪裏放置了這樣一個呼叫,以便每當請求進入(點擊這個特定的視圖,比如說get_username)時,它會產生?我曾經把這個代碼放在我的views.py中(或者是控制器類,如果它是Plyons的話)。 – user423455 2012-07-25 03:22:14

相關問題