[英]Spawning multiple greenlets using Bottlepy-Gevent
我是異步編程的新手,並且這里還介紹了Bottlepy-gevent教程。
我運行了頁面上給出的程序:
from gevent import monkey; monkey.patch_all()
from time import sleep
from bottle import route, run
@route('/stream')
def stream():
yield 'START'
sleep(3)
yield 'MIDDLE'
sleep(5)
yield 'END'
run(host='0.0.0.0', port=8080, server='gevent')
當我訪問URL http://localhost:8080/stream
時,它按預期方式工作,分別在3秒和5秒的睡眠間隔內打印START
, MIDDLE
和END
。
根據文檔,
猴子修補使gevent能夠阻止Python的阻塞API(以及諸如time.sleep()之類的函數)阻塞當前線程,並將CPU傳遞給下一個greenlet。
但是,當我修改上面的代碼以打印當前的greenlet信息時,我將相同的greenlet實例用於所有三個yield
語句。
import gevent
from gevent import monkey
monkey.patch_all()
from time import sleep
from bottle import route, run
@route('/stream')
def stream():
print(gevent.getcurrent())
yield 'START '
sleep(3)
print(gevent.getcurrent())
yield 'MIDDLE '
sleep(5)
print(gevent.getcurrent())
yield 'END'
run(host='0.0.0.0', port=8080, server='gevent')
控制台輸出:
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
根據瓶裝文檔,是否不應該在每次執行time.sleep()時生成一個新的greenlet實例?
而且,當我運行類似的程序而不使用gevent和Monkey-patching時,如下所示:
from time import sleep
from bottle import route, run
@route('/stream')
def stream():
yield 'START \n'
sleep(3)
yield 'MIDDLE \n'
sleep(5)
yield 'END'
run(host='0.0.0.0', port=8080)
我得到與以前相同的響應(START之后是MIDDLE,然后在3和5秒處結束),這與Bottlepy文檔的注釋相反,以下為黑體字:
如果運行此腳本並將瀏覽器指向http:// localhost:8080 / stream ,則應該看到START,MIDDLE和END逐一顯示( 而不是等待8秒才能一次看到它們 )。
我在這里想念什么嗎?
注意 :某些瀏覽器在開始呈現頁面之前會緩沖一定數量的數據。 您可能需要產生多個字節才能在這些瀏覽器中看到效果。 此外,許多瀏覽器每個URL最多只能有一個並發連接。 在這種情況下,您可以使用第二個瀏覽器或基准工具(例如ab或httperf)來衡量性能。
根據瓶裝文檔,是否不應該在每次執行time.sleep()時生成一個新的greenlet實例?
否。恐怕瓶子的文檔有些混亂。
為每個傳入的HTTP請求生成一個新的greenlet。 然后,生成的greenlet從頭到尾處理整個請求。 如果那個greenlet產生了(顯式或隱式),那么另一個greenlet可以自由地做一些工作(大概處理其他HTTP請求)。
當你調用monkeypatched time.sleep
,正在處理您的HTTP請求的greenlet被暫停,由此產生的任何其他活動的greenlets(如果有的話)。 當time.sleep
返回(在指定的秒數后)時,您的Greenlet(與之前為您的請求提供服務的那個Greenlet相同)被喚醒,並從sleep
調用后恢復運行。
希望有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.