使用瓶子-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')

当我访问 URLhttp://localhost:8080/stream时,它会按预期工作,打印START,然后分别以 3 秒和 5 秒的睡眠间隔MIDDLEEND

根据文档,

猴子补丁使 gevent 能够防止 Python 的阻塞 API(和 像 time.sleep()) 这样的函数阻止当前线程, 并将 CPU 传递给下一个绿色。

但是,当我修改上面的代码以打印当前的 greenlet 信息时,我得到了用于所有三个yield语句的相同 greenlet 实例。

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 和猴子补丁的情况下运行类似的程序时,如下所示:

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,您应该看到"开始"、"中间"和"结束" 一个接一个地显示(而不是等待 8 秒才能看到它们 一次)。

我在这里错过了什么吗?

2 个答案:

  • 来自服务器的每个请求都会生成一个新的greenlet,因此在同一请求中,您将看到相同的请求暂停和恢复。 尝试在同一时间发送一些请求,以查看更多greelet的打印输出。
  • 您的示例适用于我的Macchrome瓶子文档指出,您可能需要在某些浏览器上生成更多字节:

    : 某些浏览器在开始呈现页面之前会缓冲一定数量的数据。您可能需要生成超过几个字节才能在这些浏览器中看到效果。此外,许多浏览器对每个 URL 有一个并发连接的限制。如果是这种情况,您可以使用第二个浏览器或基准测试工具(例如 ab 或 httperf)来衡量性能。

根据 bottlepy 文档,每次执行 time.sleep() 时不应该生成一个新的 greenlet 实例吗?

不。恐怕瓶子文档在那里有点混乱。

为每个传入的 HTTP 请求生成一个新的绿叶。然后,生成的绿粒从头到尾处理整个请求。如果该 greenlet 产生(显式或隐式),那么另一个 greenlet 可以自由地做一些工作(大概处理其他一些 HTTP 请求)。

当你调用猴子补丁time.sleep时,处理你的HTTP请求的绿绿被挂起,从而让位于任何其他活动的绿绿(如果有的话)。当time.sleep返回时(在指定的秒数之后),您的 greenlet(与之前为您的请求提供服务的绿素完全相同)将被唤醒并从sleep调用后恢复运行。

希望对您有所帮助!

相关内容

  • 没有找到相关文章

最新更新