繁体   English   中英

使用Bottlepy-Gevent生成多个Greenlet

[英]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秒的睡眠间隔内打印STARTMIDDLEEND

根据文档,

猴子修补使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秒才能一次看到它们 )。

我在这里想念什么吗?

2个答案:

  • 来自服务器的每个请求都将产生一个新的greenlet ,因此在同一请求中,您将看到相同的暂停和恢复。 尝试同时发送一些请求,以查看更多greelet的打印输出。
  • 您的示例在使用chromeMac上运行时,bottle docs指出您可能需要在某些浏览器上产生更多字节:

    注意 :某些浏览器在开始呈现页面之前会缓冲一定数量的数据。 您可能需要产生多个字节才能在这些浏览器中看到效果。 此外,许多浏览器每个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM